listmonk-api 0.6.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.
- listmonk_api/__init__.py +83 -0
- listmonk_api/__main__.py +6 -0
- listmonk_api/agent_server.py +85 -0
- listmonk_api/api_client.py +300 -0
- listmonk_api/auth.py +36 -0
- listmonk_api/listmonk_api.py +734 -0
- listmonk_api/main_agent.json +10 -0
- listmonk_api/mcp_config.json +3 -0
- listmonk_api/mcp_server.py +444 -0
- listmonk_api/models.py +75 -0
- listmonk_api-0.6.0.dist-info/METADATA +303 -0
- listmonk_api-0.6.0.dist-info/RECORD +17 -0
- listmonk_api-0.6.0.dist-info/WHEEL +5 -0
- listmonk_api-0.6.0.dist-info/entry_points.txt +3 -0
- listmonk_api-0.6.0.dist-info/licenses/LICENSE +21 -0
- listmonk_api-0.6.0.dist-info/top_level.txt +2 -0
- tests/test_mcp_server.py +11 -0
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
# coding: utf-8
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import requests
|
|
6
|
+
import urllib3
|
|
7
|
+
from base64 import b64encode
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from agent_utilities.decorators import require_auth
|
|
11
|
+
except ModuleNotFoundError:
|
|
12
|
+
from decorators import require_auth
|
|
13
|
+
try:
|
|
14
|
+
from agent_utilities.exceptions import (
|
|
15
|
+
AuthError,
|
|
16
|
+
UnauthorizedError,
|
|
17
|
+
ParameterError,
|
|
18
|
+
MissingParameterError,
|
|
19
|
+
)
|
|
20
|
+
except ModuleNotFoundError:
|
|
21
|
+
from exceptions import (
|
|
22
|
+
AuthError,
|
|
23
|
+
UnauthorizedError,
|
|
24
|
+
ParameterError,
|
|
25
|
+
MissingParameterError,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Api(object):
|
|
30
|
+
def __init__(self, url=None, username=None, password=None, token=None, verify=True):
|
|
31
|
+
if url is None:
|
|
32
|
+
raise MissingParameterError
|
|
33
|
+
|
|
34
|
+
self._session = requests.Session()
|
|
35
|
+
self.url = url
|
|
36
|
+
self.headers = None
|
|
37
|
+
self.verify = verify
|
|
38
|
+
|
|
39
|
+
if self.verify is False:
|
|
40
|
+
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
41
|
+
|
|
42
|
+
if token:
|
|
43
|
+
self.headers = {
|
|
44
|
+
"Authorization": f"Bearer {token}",
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
}
|
|
47
|
+
elif username and password:
|
|
48
|
+
user_pass = f"{username}:{password}".encode()
|
|
49
|
+
user_pass_encoded = b64encode(user_pass).decode()
|
|
50
|
+
self.headers = {
|
|
51
|
+
"Authorization": f"Basic {user_pass_encoded}",
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
}
|
|
54
|
+
else:
|
|
55
|
+
raise MissingParameterError
|
|
56
|
+
|
|
57
|
+
response = self._session.get(
|
|
58
|
+
f"{self.url}/subscribers", headers=self.headers, verify=self.verify
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if response.status_code == 403:
|
|
62
|
+
raise UnauthorizedError
|
|
63
|
+
elif response.status_code == 401:
|
|
64
|
+
raise AuthError
|
|
65
|
+
elif response.status_code == 404:
|
|
66
|
+
raise ParameterError
|
|
67
|
+
|
|
68
|
+
####################################################################################################################
|
|
69
|
+
# Subscribers API #
|
|
70
|
+
####################################################################################################################
|
|
71
|
+
@require_auth
|
|
72
|
+
def get_subscribers(self, query=None, list_id=None, max_pages=0, per_page=100):
|
|
73
|
+
data = None
|
|
74
|
+
response = self._session.get(
|
|
75
|
+
f"{self.url}/subscribers?per_page={per_page}&x-total-pages",
|
|
76
|
+
headers=self.headers,
|
|
77
|
+
verify=self.verify,
|
|
78
|
+
)
|
|
79
|
+
total_pages = int(response.headers["X-Total-Pages"])
|
|
80
|
+
response = []
|
|
81
|
+
subscriber_filter = f"?per_page={per_page}"
|
|
82
|
+
if query:
|
|
83
|
+
try:
|
|
84
|
+
data = json.dumps(query, indent=4)
|
|
85
|
+
except ValueError:
|
|
86
|
+
raise ParameterError
|
|
87
|
+
if list_id:
|
|
88
|
+
if not isinstance(list_id, int) and not isinstance(list_id, list):
|
|
89
|
+
raise ParameterError
|
|
90
|
+
if isinstance(list_id, list):
|
|
91
|
+
for single_list_id in list_id:
|
|
92
|
+
subscriber_filter = f"{subscriber_filter}&list_id={single_list_id}"
|
|
93
|
+
else:
|
|
94
|
+
subscriber_filter = f"{subscriber_filter}&list_id={list_id}"
|
|
95
|
+
if max_pages == 0 or max_pages > total_pages:
|
|
96
|
+
max_pages = total_pages
|
|
97
|
+
for page in range(0, max_pages):
|
|
98
|
+
response_page = self._session.get(
|
|
99
|
+
f"{self.url}/subscribers{subscriber_filter}&page={page}",
|
|
100
|
+
headers=self.headers,
|
|
101
|
+
data=data,
|
|
102
|
+
verify=self.verify,
|
|
103
|
+
)
|
|
104
|
+
response_page = json.loads(response_page.text.replace('"', '"'))
|
|
105
|
+
response = response + response_page
|
|
106
|
+
try:
|
|
107
|
+
return response.json()
|
|
108
|
+
except ValueError or AttributeError:
|
|
109
|
+
return response
|
|
110
|
+
|
|
111
|
+
@require_auth
|
|
112
|
+
def get_subscriber(self, subscriber_id=None):
|
|
113
|
+
if subscriber_id is None:
|
|
114
|
+
raise MissingParameterError
|
|
115
|
+
response = self._session.get(
|
|
116
|
+
f"{self.url}/subscribers/{subscriber_id}",
|
|
117
|
+
headers=self.headers,
|
|
118
|
+
verify=self.verify,
|
|
119
|
+
)
|
|
120
|
+
try:
|
|
121
|
+
return response.json()
|
|
122
|
+
except ValueError or AttributeError:
|
|
123
|
+
return response
|
|
124
|
+
|
|
125
|
+
@require_auth
|
|
126
|
+
def get_subscribers_from_list(self, list_id=None):
|
|
127
|
+
if list_id is None:
|
|
128
|
+
raise MissingParameterError
|
|
129
|
+
response = self._session.get(
|
|
130
|
+
f"{self.url}/subscribers/lists/{list_id}",
|
|
131
|
+
headers=self.headers,
|
|
132
|
+
verify=self.verify,
|
|
133
|
+
)
|
|
134
|
+
try:
|
|
135
|
+
return response.json()
|
|
136
|
+
except ValueError or AttributeError:
|
|
137
|
+
return response
|
|
138
|
+
|
|
139
|
+
@require_auth
|
|
140
|
+
def create_subscriber(
|
|
141
|
+
self,
|
|
142
|
+
email=None,
|
|
143
|
+
name=None,
|
|
144
|
+
status=None,
|
|
145
|
+
lists=None,
|
|
146
|
+
attributes=None,
|
|
147
|
+
preconfirm_subscriptions=True,
|
|
148
|
+
):
|
|
149
|
+
if email is None or name is None or status is None:
|
|
150
|
+
raise MissingParameterError
|
|
151
|
+
if isinstance(email, str) and isinstance(name, str) and isinstance(status, str):
|
|
152
|
+
data = {"email": email, "name": name, "status": status}
|
|
153
|
+
else:
|
|
154
|
+
raise ParameterError
|
|
155
|
+
if lists and isinstance(lists, list):
|
|
156
|
+
data["lists"] = lists
|
|
157
|
+
if attributes and isinstance(attributes, dict):
|
|
158
|
+
data["attribs"] = attributes
|
|
159
|
+
if isinstance(preconfirm_subscriptions, bool):
|
|
160
|
+
data["preconfirm_subscriptions"] = preconfirm_subscriptions
|
|
161
|
+
try:
|
|
162
|
+
data = json.dumps(data, indent=4)
|
|
163
|
+
except ValueError:
|
|
164
|
+
raise ParameterError
|
|
165
|
+
response = self._session.post(
|
|
166
|
+
f"{self.url}/subscribers",
|
|
167
|
+
headers=self.headers,
|
|
168
|
+
data=data,
|
|
169
|
+
verify=self.verify,
|
|
170
|
+
)
|
|
171
|
+
try:
|
|
172
|
+
return response.json()
|
|
173
|
+
except ValueError or AttributeError:
|
|
174
|
+
return response
|
|
175
|
+
|
|
176
|
+
####################################################################################################################
|
|
177
|
+
# Lists API #
|
|
178
|
+
####################################################################################################################
|
|
179
|
+
@require_auth
|
|
180
|
+
def get_lists(
|
|
181
|
+
self, query=None, order_by=None, order=None, max_pages=0, per_page=100
|
|
182
|
+
):
|
|
183
|
+
data = None
|
|
184
|
+
response = self._session.get(
|
|
185
|
+
f"{self.url}/lists?per_page={per_page}&x-total-pages",
|
|
186
|
+
headers=self.headers,
|
|
187
|
+
verify=self.verify,
|
|
188
|
+
)
|
|
189
|
+
total_pages = int(response.headers["X-Total-Pages"])
|
|
190
|
+
response = []
|
|
191
|
+
list_filter = f"?per_page={per_page}"
|
|
192
|
+
if query:
|
|
193
|
+
try:
|
|
194
|
+
data = json.dumps(query, indent=4)
|
|
195
|
+
except ValueError:
|
|
196
|
+
raise ParameterError
|
|
197
|
+
if order_by and order_by in ["name", "status", "created_at", "updated_at"]:
|
|
198
|
+
list_filter = f"{list_filter}&order_by={order_by}"
|
|
199
|
+
if order and order.upper() in ["ASC", "DESC"]:
|
|
200
|
+
list_filter = f"{list_filter}&order={order}"
|
|
201
|
+
if max_pages == 0 or max_pages > total_pages:
|
|
202
|
+
max_pages = total_pages
|
|
203
|
+
for page in range(0, max_pages):
|
|
204
|
+
response_page = self._session.get(
|
|
205
|
+
f"{self.url}/lists{list_filter}&page={page}",
|
|
206
|
+
headers=self.headers,
|
|
207
|
+
data=data,
|
|
208
|
+
verify=self.verify,
|
|
209
|
+
)
|
|
210
|
+
response_page = json.loads(response_page.text.replace('"', '"'))
|
|
211
|
+
response = response + response_page
|
|
212
|
+
try:
|
|
213
|
+
return response.json()
|
|
214
|
+
except ValueError or AttributeError:
|
|
215
|
+
return response
|
|
216
|
+
|
|
217
|
+
@require_auth
|
|
218
|
+
def get_list(self, list_id=None):
|
|
219
|
+
if list_id is None:
|
|
220
|
+
raise MissingParameterError
|
|
221
|
+
response = self._session.get(
|
|
222
|
+
f"{self.url}/lists/{list_id}", headers=self.headers, verify=self.verify
|
|
223
|
+
)
|
|
224
|
+
try:
|
|
225
|
+
return response.json()
|
|
226
|
+
except ValueError or AttributeError:
|
|
227
|
+
return response
|
|
228
|
+
|
|
229
|
+
@require_auth
|
|
230
|
+
def create_list(self, name=None, visibility_type=None, optin=None, tags=None):
|
|
231
|
+
if name is None or type is None or optin is None:
|
|
232
|
+
raise MissingParameterError
|
|
233
|
+
data = {}
|
|
234
|
+
if name:
|
|
235
|
+
if not isinstance(name, str):
|
|
236
|
+
raise ParameterError
|
|
237
|
+
else:
|
|
238
|
+
data["name"] = name
|
|
239
|
+
if visibility_type:
|
|
240
|
+
if not isinstance(visibility_type, str) and optin not in [
|
|
241
|
+
"private",
|
|
242
|
+
"public",
|
|
243
|
+
]:
|
|
244
|
+
raise ParameterError
|
|
245
|
+
else:
|
|
246
|
+
data["type"] = visibility_type
|
|
247
|
+
if optin:
|
|
248
|
+
if not isinstance(optin, str) and optin not in ["single", "double"]:
|
|
249
|
+
raise ParameterError
|
|
250
|
+
else:
|
|
251
|
+
data["optin"] = optin
|
|
252
|
+
if tags:
|
|
253
|
+
if not isinstance(tags, list):
|
|
254
|
+
raise ParameterError
|
|
255
|
+
else:
|
|
256
|
+
data["tags"] = tags
|
|
257
|
+
try:
|
|
258
|
+
data = json.dumps(data, indent=4)
|
|
259
|
+
except ValueError:
|
|
260
|
+
raise ParameterError
|
|
261
|
+
response = self._session.post(
|
|
262
|
+
f"{self.url}/lists", data=data, headers=self.headers, verify=self.verify
|
|
263
|
+
)
|
|
264
|
+
try:
|
|
265
|
+
return response.json()
|
|
266
|
+
except ValueError or AttributeError:
|
|
267
|
+
return response
|
|
268
|
+
|
|
269
|
+
@require_auth
|
|
270
|
+
def edit_list(
|
|
271
|
+
self, list_id=None, name=None, visibility_type=None, optin=None, tags=None
|
|
272
|
+
):
|
|
273
|
+
if list_id is None:
|
|
274
|
+
raise MissingParameterError
|
|
275
|
+
data = {}
|
|
276
|
+
if name:
|
|
277
|
+
if not isinstance(name, str):
|
|
278
|
+
raise ParameterError
|
|
279
|
+
else:
|
|
280
|
+
data["name"] = name
|
|
281
|
+
if visibility_type:
|
|
282
|
+
if not isinstance(visibility_type, str) and optin not in [
|
|
283
|
+
"private",
|
|
284
|
+
"public",
|
|
285
|
+
]:
|
|
286
|
+
raise ParameterError
|
|
287
|
+
else:
|
|
288
|
+
data["type"] = visibility_type
|
|
289
|
+
if optin:
|
|
290
|
+
if not isinstance(optin, str) and optin not in ["single", "double"]:
|
|
291
|
+
raise ParameterError
|
|
292
|
+
else:
|
|
293
|
+
data["optin"] = optin
|
|
294
|
+
if tags:
|
|
295
|
+
if not isinstance(tags, list):
|
|
296
|
+
raise ParameterError
|
|
297
|
+
else:
|
|
298
|
+
data["tags"] = tags
|
|
299
|
+
try:
|
|
300
|
+
data = json.dumps(data, indent=4)
|
|
301
|
+
except ValueError:
|
|
302
|
+
raise ParameterError
|
|
303
|
+
response = self._session.put(
|
|
304
|
+
f"{self.url}/lists/{list_id}",
|
|
305
|
+
data=data,
|
|
306
|
+
headers=self.headers,
|
|
307
|
+
verify=self.verify,
|
|
308
|
+
)
|
|
309
|
+
try:
|
|
310
|
+
return response.json()
|
|
311
|
+
except ValueError or AttributeError:
|
|
312
|
+
return response
|
|
313
|
+
|
|
314
|
+
####################################################################################################################
|
|
315
|
+
# Import API #
|
|
316
|
+
####################################################################################################################
|
|
317
|
+
@require_auth
|
|
318
|
+
def get_subscriber_import_status(self):
|
|
319
|
+
response = self._session.get(
|
|
320
|
+
f"{self.url}/import/subscribers", headers=self.headers, verify=self.verify
|
|
321
|
+
)
|
|
322
|
+
try:
|
|
323
|
+
return response.json()
|
|
324
|
+
except ValueError or AttributeError:
|
|
325
|
+
return response
|
|
326
|
+
|
|
327
|
+
@require_auth
|
|
328
|
+
def get_subscriber_import_logs(self):
|
|
329
|
+
response = self._session.get(
|
|
330
|
+
f"{self.url}/import/subscribers/logs",
|
|
331
|
+
headers=self.headers,
|
|
332
|
+
verify=self.verify,
|
|
333
|
+
)
|
|
334
|
+
try:
|
|
335
|
+
return response.json()
|
|
336
|
+
except ValueError or AttributeError:
|
|
337
|
+
return response
|
|
338
|
+
|
|
339
|
+
@require_auth
|
|
340
|
+
def import_subscribers(
|
|
341
|
+
self, file=None, mode=None, delimiter=",", id_list=None, overwrite=True
|
|
342
|
+
):
|
|
343
|
+
if file is None or mode is None or id_list is None:
|
|
344
|
+
raise MissingParameterError
|
|
345
|
+
if not isinstance(id_list, list):
|
|
346
|
+
raise ParameterError
|
|
347
|
+
if mode not in ["subscribe", "blocklist"]:
|
|
348
|
+
raise ParameterError
|
|
349
|
+
if not isinstance(delimiter, str):
|
|
350
|
+
raise ParameterError
|
|
351
|
+
if not isinstance(overwrite, bool):
|
|
352
|
+
raise ParameterError
|
|
353
|
+
data = {
|
|
354
|
+
"file": file,
|
|
355
|
+
"mode": mode,
|
|
356
|
+
"delim": delimiter,
|
|
357
|
+
"lists": id_list,
|
|
358
|
+
"overwrite": overwrite,
|
|
359
|
+
}
|
|
360
|
+
try:
|
|
361
|
+
data = json.dumps(data, indent=4)
|
|
362
|
+
except ValueError:
|
|
363
|
+
raise ParameterError
|
|
364
|
+
response = self._session.get(
|
|
365
|
+
f"{self.url}/import/subscribers/",
|
|
366
|
+
headers=self.headers,
|
|
367
|
+
data=data,
|
|
368
|
+
verify=self.verify,
|
|
369
|
+
)
|
|
370
|
+
try:
|
|
371
|
+
return response.json()
|
|
372
|
+
except ValueError or AttributeError:
|
|
373
|
+
return response
|
|
374
|
+
|
|
375
|
+
@require_auth
|
|
376
|
+
def delete_subscriber_import(self):
|
|
377
|
+
response = self._session.delete(
|
|
378
|
+
f"{self.url}/import/subscribers/logs",
|
|
379
|
+
headers=self.headers,
|
|
380
|
+
verify=self.verify,
|
|
381
|
+
)
|
|
382
|
+
try:
|
|
383
|
+
return response.json()
|
|
384
|
+
except ValueError or AttributeError:
|
|
385
|
+
return response
|
|
386
|
+
|
|
387
|
+
####################################################################################################################
|
|
388
|
+
# Campaigns API #
|
|
389
|
+
####################################################################################################################
|
|
390
|
+
@require_auth
|
|
391
|
+
def get_campaigns(
|
|
392
|
+
self, query=None, order_by=None, order=None, max_pages=0, per_page=100
|
|
393
|
+
):
|
|
394
|
+
data = None
|
|
395
|
+
response = self._session.get(
|
|
396
|
+
f"{self.url}/campaigns?per_page={per_page}&x-total-pages",
|
|
397
|
+
headers=self.headers,
|
|
398
|
+
verify=self.verify,
|
|
399
|
+
)
|
|
400
|
+
total_pages = int(response.headers["X-Total-Pages"])
|
|
401
|
+
response = []
|
|
402
|
+
campaign_filter = f"?per_page={per_page}"
|
|
403
|
+
if query:
|
|
404
|
+
try:
|
|
405
|
+
data = json.dumps(query, indent=4)
|
|
406
|
+
except ValueError:
|
|
407
|
+
raise ParameterError
|
|
408
|
+
if order_by and order_by in ["name", "status", "created_at", "updated_at"]:
|
|
409
|
+
campaign_filter = f"{campaign_filter}&order_by={order_by}"
|
|
410
|
+
if order and order.upper() in ["ASC", "DESC"]:
|
|
411
|
+
campaign_filter = f"{campaign_filter}&order={order}"
|
|
412
|
+
if max_pages == 0 or max_pages > total_pages:
|
|
413
|
+
max_pages = total_pages
|
|
414
|
+
for page in range(0, max_pages):
|
|
415
|
+
response_page = self._session.get(
|
|
416
|
+
f"{self.url}/campaigns{campaign_filter}&page={page}",
|
|
417
|
+
headers=self.headers,
|
|
418
|
+
data=data,
|
|
419
|
+
verify=self.verify,
|
|
420
|
+
)
|
|
421
|
+
response_page = json.loads(response_page.text.replace('"', '"'))
|
|
422
|
+
response = response + response_page
|
|
423
|
+
try:
|
|
424
|
+
return response.json()
|
|
425
|
+
except ValueError or AttributeError:
|
|
426
|
+
return response
|
|
427
|
+
|
|
428
|
+
@require_auth
|
|
429
|
+
def get_campaign(self, campaign_id=None):
|
|
430
|
+
if campaign_id is None:
|
|
431
|
+
raise MissingParameterError
|
|
432
|
+
response = self._session.get(
|
|
433
|
+
f"{self.url}/campaigns/{campaign_id}",
|
|
434
|
+
headers=self.headers,
|
|
435
|
+
verify=self.verify,
|
|
436
|
+
)
|
|
437
|
+
try:
|
|
438
|
+
return response.json()
|
|
439
|
+
except ValueError or AttributeError:
|
|
440
|
+
return response
|
|
441
|
+
|
|
442
|
+
@require_auth
|
|
443
|
+
def get_campaign_preview(self, campaign_id=None):
|
|
444
|
+
if campaign_id is None:
|
|
445
|
+
raise MissingParameterError
|
|
446
|
+
response = self._session.get(
|
|
447
|
+
f"{self.url}/campaigns/{campaign_id}/preview",
|
|
448
|
+
headers=self.headers,
|
|
449
|
+
verify=self.verify,
|
|
450
|
+
)
|
|
451
|
+
try:
|
|
452
|
+
return response.json()
|
|
453
|
+
except ValueError or AttributeError:
|
|
454
|
+
return response
|
|
455
|
+
|
|
456
|
+
@require_auth
|
|
457
|
+
def get_campaign_stats(self, campaign_id=None):
|
|
458
|
+
if campaign_id is None:
|
|
459
|
+
raise MissingParameterError
|
|
460
|
+
response = self._session.get(
|
|
461
|
+
f"{self.url}/campaigns/{campaign_id}/running/stats?campaign_id={campaign_id}",
|
|
462
|
+
headers=self.headers,
|
|
463
|
+
verify=self.verify,
|
|
464
|
+
)
|
|
465
|
+
try:
|
|
466
|
+
return response.json()
|
|
467
|
+
except ValueError or AttributeError:
|
|
468
|
+
return response
|
|
469
|
+
|
|
470
|
+
@require_auth
|
|
471
|
+
def create_campaign(
|
|
472
|
+
self,
|
|
473
|
+
name=None,
|
|
474
|
+
subject=None,
|
|
475
|
+
lists=None,
|
|
476
|
+
from_email=None,
|
|
477
|
+
send_type=None,
|
|
478
|
+
content_type=None,
|
|
479
|
+
body=None,
|
|
480
|
+
altbody=None,
|
|
481
|
+
send_at=None,
|
|
482
|
+
messenger=None,
|
|
483
|
+
template_id=None,
|
|
484
|
+
tags=None,
|
|
485
|
+
):
|
|
486
|
+
if (
|
|
487
|
+
name is None
|
|
488
|
+
or subject is None
|
|
489
|
+
or lists is None
|
|
490
|
+
or send_type is None
|
|
491
|
+
or content_type is None
|
|
492
|
+
or body is None
|
|
493
|
+
):
|
|
494
|
+
raise MissingParameterError
|
|
495
|
+
data = {}
|
|
496
|
+
if isinstance(name, str):
|
|
497
|
+
data["name"] = name
|
|
498
|
+
if isinstance(subject, str):
|
|
499
|
+
data["subject"] = subject
|
|
500
|
+
if isinstance(lists, list):
|
|
501
|
+
data["lists"] = lists
|
|
502
|
+
if isinstance(from_email, str):
|
|
503
|
+
data["from_email"] = from_email
|
|
504
|
+
if send_type in ["regular", "optin"]:
|
|
505
|
+
data["send_type"] = send_type
|
|
506
|
+
else:
|
|
507
|
+
raise ParameterError
|
|
508
|
+
if content_type in ["richtext", "html", "markdown", "plain"]:
|
|
509
|
+
data["content_type"] = content_type
|
|
510
|
+
else:
|
|
511
|
+
raise ParameterError
|
|
512
|
+
if isinstance(body, str):
|
|
513
|
+
data["body"] = body
|
|
514
|
+
if isinstance(altbody, str):
|
|
515
|
+
data["altbody"] = altbody
|
|
516
|
+
if isinstance(send_at, str):
|
|
517
|
+
data["send_at"] = send_at
|
|
518
|
+
if isinstance(messenger, str):
|
|
519
|
+
data["messenger"] = messenger
|
|
520
|
+
if isinstance(template_id, int):
|
|
521
|
+
data["template_id"] = template_id
|
|
522
|
+
if isinstance(tags, list):
|
|
523
|
+
data["tags"] = tags
|
|
524
|
+
try:
|
|
525
|
+
data = json.dumps(data, indent=4)
|
|
526
|
+
except ValueError or AttributeError:
|
|
527
|
+
raise ParameterError
|
|
528
|
+
response = self._session.post(
|
|
529
|
+
f"{self.url}/campaigns", data=data, headers=self.headers, verify=self.verify
|
|
530
|
+
)
|
|
531
|
+
try:
|
|
532
|
+
return response.json()
|
|
533
|
+
except ValueError or AttributeError:
|
|
534
|
+
return response
|
|
535
|
+
|
|
536
|
+
@require_auth
|
|
537
|
+
def set_campaign_status(self, campaign_id=None, status=None):
|
|
538
|
+
if campaign_id is None or status is None:
|
|
539
|
+
raise MissingParameterError
|
|
540
|
+
if status and status in ["scheduled", "running", "paused", "cancelled"]:
|
|
541
|
+
data = {"status": status}
|
|
542
|
+
try:
|
|
543
|
+
data = json.dumps(data, indent=4)
|
|
544
|
+
except ValueError or AttributeError:
|
|
545
|
+
raise ParameterError
|
|
546
|
+
else:
|
|
547
|
+
raise ParameterError
|
|
548
|
+
response = self._session.put(
|
|
549
|
+
f"{self.url}/campaigns/{campaign_id}/status",
|
|
550
|
+
data=data,
|
|
551
|
+
headers=self.headers,
|
|
552
|
+
verify=self.verify,
|
|
553
|
+
)
|
|
554
|
+
try:
|
|
555
|
+
return response.json()
|
|
556
|
+
except ValueError or AttributeError:
|
|
557
|
+
return response
|
|
558
|
+
|
|
559
|
+
@require_auth
|
|
560
|
+
def delete_campaign(self, campaign_id=None):
|
|
561
|
+
if campaign_id is None:
|
|
562
|
+
raise MissingParameterError
|
|
563
|
+
response = self._session.delete(
|
|
564
|
+
f"{self.url}/campaigns/{campaign_id}",
|
|
565
|
+
headers=self.headers,
|
|
566
|
+
verify=self.verify,
|
|
567
|
+
)
|
|
568
|
+
try:
|
|
569
|
+
return response.json()
|
|
570
|
+
except ValueError or AttributeError:
|
|
571
|
+
return response
|
|
572
|
+
|
|
573
|
+
####################################################################################################################
|
|
574
|
+
# Media API #
|
|
575
|
+
####################################################################################################################
|
|
576
|
+
@require_auth
|
|
577
|
+
def get_media(self, media_id=None):
|
|
578
|
+
if media_id is None:
|
|
579
|
+
raise MissingParameterError
|
|
580
|
+
response = self._session.get(
|
|
581
|
+
f"{self.url}/media", headers=self.headers, verify=self.verify
|
|
582
|
+
)
|
|
583
|
+
try:
|
|
584
|
+
return response.json()
|
|
585
|
+
except ValueError or AttributeError:
|
|
586
|
+
return response
|
|
587
|
+
|
|
588
|
+
@require_auth
|
|
589
|
+
def upload_media(self, file=None):
|
|
590
|
+
if file is None:
|
|
591
|
+
raise MissingParameterError
|
|
592
|
+
data = {"file": file}
|
|
593
|
+
response = self._session.post(
|
|
594
|
+
f"{self.url}/media", data=data, headers=self.headers, verify=self.verify
|
|
595
|
+
)
|
|
596
|
+
try:
|
|
597
|
+
return response.json()
|
|
598
|
+
except ValueError or AttributeError:
|
|
599
|
+
return response
|
|
600
|
+
|
|
601
|
+
@require_auth
|
|
602
|
+
def delete_media(self, media_id=None):
|
|
603
|
+
if media_id is None:
|
|
604
|
+
raise MissingParameterError
|
|
605
|
+
response = self._session.delete(
|
|
606
|
+
f"{self.url}/media/{media_id}", headers=self.headers, verify=self.verify
|
|
607
|
+
)
|
|
608
|
+
try:
|
|
609
|
+
return response.json()
|
|
610
|
+
except ValueError or AttributeError:
|
|
611
|
+
return response
|
|
612
|
+
|
|
613
|
+
####################################################################################################################
|
|
614
|
+
# Templates API #
|
|
615
|
+
####################################################################################################################
|
|
616
|
+
@require_auth
|
|
617
|
+
def get_templates(self, max_pages=0, per_page=100):
|
|
618
|
+
data = None
|
|
619
|
+
response = self._session.get(
|
|
620
|
+
f"{self.url}/templates?per_page={per_page}&x-total-pages",
|
|
621
|
+
headers=self.headers,
|
|
622
|
+
verify=self.verify,
|
|
623
|
+
)
|
|
624
|
+
total_pages = int(response.headers["X-Total-Pages"])
|
|
625
|
+
response = []
|
|
626
|
+
campaign_filter = f"?per_page={per_page}"
|
|
627
|
+
if max_pages == 0 or max_pages > total_pages:
|
|
628
|
+
max_pages = total_pages
|
|
629
|
+
for page in range(0, max_pages):
|
|
630
|
+
response_page = self._session.get(
|
|
631
|
+
f"{self.url}/templates{campaign_filter}&page={page}",
|
|
632
|
+
headers=self.headers,
|
|
633
|
+
data=data,
|
|
634
|
+
verify=self.verify,
|
|
635
|
+
)
|
|
636
|
+
response_page = json.loads(response_page.text.replace('"', '"'))
|
|
637
|
+
response = response + response_page
|
|
638
|
+
try:
|
|
639
|
+
return response.json()
|
|
640
|
+
except ValueError or AttributeError:
|
|
641
|
+
return response
|
|
642
|
+
|
|
643
|
+
@require_auth
|
|
644
|
+
def get_template(self, template_id=None):
|
|
645
|
+
if template_id is None:
|
|
646
|
+
raise MissingParameterError
|
|
647
|
+
response = self._session.get(
|
|
648
|
+
f"{self.url}/templates/{template_id}",
|
|
649
|
+
headers=self.headers,
|
|
650
|
+
verify=self.verify,
|
|
651
|
+
)
|
|
652
|
+
try:
|
|
653
|
+
return response.json()
|
|
654
|
+
except ValueError or AttributeError:
|
|
655
|
+
return response
|
|
656
|
+
|
|
657
|
+
@require_auth
|
|
658
|
+
def get_template_preview(self, template_id=None):
|
|
659
|
+
if template_id is None:
|
|
660
|
+
raise MissingParameterError
|
|
661
|
+
response = self._session.get(
|
|
662
|
+
f"{self.url}/templates/{template_id}/preview",
|
|
663
|
+
headers=self.headers,
|
|
664
|
+
verify=self.verify,
|
|
665
|
+
)
|
|
666
|
+
try:
|
|
667
|
+
return response.json()
|
|
668
|
+
except ValueError or AttributeError:
|
|
669
|
+
return response
|
|
670
|
+
|
|
671
|
+
@require_auth
|
|
672
|
+
def set_default_template(self, template_id=None):
|
|
673
|
+
if template_id is None:
|
|
674
|
+
raise MissingParameterError
|
|
675
|
+
response = self._session.put(
|
|
676
|
+
f"{self.url}/templates/{template_id}/default",
|
|
677
|
+
headers=self.headers,
|
|
678
|
+
verify=self.verify,
|
|
679
|
+
)
|
|
680
|
+
try:
|
|
681
|
+
return response.json()
|
|
682
|
+
except ValueError or AttributeError:
|
|
683
|
+
return response
|
|
684
|
+
|
|
685
|
+
@require_auth
|
|
686
|
+
def delete_template(self, template_id=None):
|
|
687
|
+
if template_id is None:
|
|
688
|
+
raise MissingParameterError
|
|
689
|
+
response = self._session.delete(
|
|
690
|
+
f"{self.url}/templates/{template_id}",
|
|
691
|
+
headers=self.headers,
|
|
692
|
+
verify=self.verify,
|
|
693
|
+
)
|
|
694
|
+
try:
|
|
695
|
+
return response.json()
|
|
696
|
+
except ValueError or AttributeError:
|
|
697
|
+
return response
|
|
698
|
+
|
|
699
|
+
####################################################################################################################
|
|
700
|
+
# Transactional API #
|
|
701
|
+
####################################################################################################################
|
|
702
|
+
@require_auth
|
|
703
|
+
def transactional_message(
|
|
704
|
+
self,
|
|
705
|
+
template_id=None,
|
|
706
|
+
subscriber_email=None,
|
|
707
|
+
subscriber_id=None,
|
|
708
|
+
additional_data=None,
|
|
709
|
+
headers=None,
|
|
710
|
+
content_type=None,
|
|
711
|
+
):
|
|
712
|
+
if template_id is None:
|
|
713
|
+
raise MissingParameterError
|
|
714
|
+
data = {"template_id": template_id}
|
|
715
|
+
if subscriber_id:
|
|
716
|
+
data["subscriber_id"]: subscriber_id
|
|
717
|
+
elif subscriber_email:
|
|
718
|
+
data["subscriber_email"]: subscriber_email
|
|
719
|
+
if additional_data:
|
|
720
|
+
data["data"]: additional_data
|
|
721
|
+
if headers:
|
|
722
|
+
data["headers"]: headers
|
|
723
|
+
if content_type:
|
|
724
|
+
if content_type in ["html", "markdown", "plain"]:
|
|
725
|
+
data["content_type"]: content_type
|
|
726
|
+
else:
|
|
727
|
+
raise ParameterError
|
|
728
|
+
response = self._session.post(
|
|
729
|
+
f"{self.url}/tx", data=data, headers=self.headers, verify=self.verify
|
|
730
|
+
)
|
|
731
|
+
try:
|
|
732
|
+
return response.json()
|
|
733
|
+
except ValueError or AttributeError:
|
|
734
|
+
return response
|