sendbee-api 1.6.4__tar.gz → 1.7.2__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.
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/PKG-INFO +43 -30
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/README.md +21 -20
- sendbee_api-1.7.2/pyproject.toml +46 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/automation/models.py +1 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/automation/query_params.py +1 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/bind.py +35 -15
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/client.py +2 -1
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/constants.py +26 -2
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/conversations/models.py +2 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/conversations/query_params.py +2 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/debug.py +8 -1
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/exceptions.py +3 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/formatter.py +16 -0
- sendbee_api-1.7.2/sendbee_api/rate_limit/client.py +26 -0
- sendbee_api-1.7.2/sendbee_api/rate_limit/models.py +10 -0
- sendbee_api-1.7.2/sendbee_api/rate_limit/query_params.py +5 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/response.py +14 -2
- sendbee_api-1.7.2/sendbee_api/teams/__init__.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api.egg-info/PKG-INFO +44 -31
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api.egg-info/SOURCES.txt +15 -2
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api.egg-info/requires.txt +6 -1
- sendbee_api-1.7.2/tests/test_auth.py +110 -0
- sendbee_api-1.7.2/tests/test_bind_request.py +476 -0
- sendbee_api-1.7.2/tests/test_client.py +67 -0
- sendbee_api-1.7.2/tests/test_endpoints_smoke.py +177 -0
- sendbee_api-1.7.2/tests/test_fields.py +105 -0
- sendbee_api-1.7.2/tests/test_formatter.py +79 -0
- sendbee_api-1.7.2/tests/test_models.py +99 -0
- sendbee_api-1.7.2/tests/test_query_params.py +59 -0
- sendbee_api-1.7.2/tests/test_response.py +112 -0
- sendbee_api-1.6.4/setup.py +0 -47
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/LICENSE +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/__init__.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/auth.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/automation/__init__.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/automation/client.py +1 -1
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/contacts/__init__.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/contacts/client.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/contacts/models.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/contacts/query_params.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/conversations/__init__.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/conversations/client.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/fields.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/models.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/query_params.py +0 -0
- {sendbee_api-1.6.4/sendbee_api/teams → sendbee_api-1.7.2/sendbee_api/rate_limit}/__init__.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/teams/client.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/teams/models.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api/teams/query_params.py +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api.egg-info/dependency_links.txt +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/sendbee_api.egg-info/top_level.txt +0 -0
- {sendbee_api-1.6.4 → sendbee_api-1.7.2}/setup.cfg +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: sendbee_api
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.2
|
|
4
4
|
Summary: Python client SDK for Sendbee Public API
|
|
5
|
-
|
|
6
|
-
Author: Sendbee ltd
|
|
7
|
-
Author-email: info@sendbee.io
|
|
5
|
+
Author-email: Sendbee ltd <info@sendbee.io>
|
|
8
6
|
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sendbee/sendbee-python-client
|
|
9
8
|
Project-URL: Source, https://github.com/sendbee/sendbee-python-client
|
|
10
|
-
Keywords: sendbee
|
|
11
|
-
Platform: UNKNOWN
|
|
9
|
+
Keywords: sendbee,api,python
|
|
12
10
|
Classifier: Intended Audience :: Developers
|
|
13
11
|
Classifier: Topic :: Software Development :: Build Tools
|
|
14
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -16,30 +14,28 @@ Classifier: Programming Language :: Python :: 3.6
|
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.7
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.8
|
|
18
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
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Requires-Python: >=3.6
|
|
19
22
|
Description-Content-Type: text/markdown
|
|
20
23
|
License-File: LICENSE
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
Requires-Dist: click>=7.0
|
|
25
|
+
Requires-Dist: requests>=2.20.0
|
|
26
|
+
Requires-Dist: dumpit>=0.5.0
|
|
27
|
+
Requires-Dist: aenum>=2.1.2
|
|
28
|
+
Requires-Dist: ujson<6,>=5.7.0
|
|
29
|
+
Requires-Dist: cryptography>=3.2
|
|
30
|
+
Requires-Dist: curlify>=2.2.1
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest; extra == "dev"
|
|
33
|
+
Requires-Dist: responses>=0.23; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# AI Number Python API Client
|
|
32
37
|
|
|
33
38
|
[](https://badge.fury.io/py/sendbee-api)
|
|
34
|
-
[](https://travis-ci.org/sendbee/sendbee-python-api-client)
|
|
35
|
-
|
|
36
|
-

|
|
37
|
-

|
|
38
|
-

|
|
39
|
-
|
|
40
|
-

|
|
41
|
-

|
|
42
|
-

|
|
43
39
|
|
|
44
40
|
## Table of contents
|
|
45
41
|
|
|
@@ -87,6 +83,7 @@ License-File: LICENSE
|
|
|
87
83
|
#### Mics
|
|
88
84
|
|
|
89
85
|
- [Pagination](#pagination)
|
|
86
|
+
- [API Rate Limit](#api-rate-limit)
|
|
90
87
|
- [Raw response](#raw-response)
|
|
91
88
|
- [Exception handling](#exception-handling)
|
|
92
89
|
- [Authenticate webhook request](#authenticate-webhook-request)
|
|
@@ -594,7 +591,25 @@ while True:
|
|
|
594
591
|
messages = api.messages(
|
|
595
592
|
conversation_id='...', page=messages.next_page()
|
|
596
593
|
)
|
|
597
|
-
```
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### <a href='#api-rate-limit'>API Rate Limit</a>
|
|
597
|
+
|
|
598
|
+
A rate limit is the number of API calls a business number can make
|
|
599
|
+
within a given time period. If this limit is exceeded,
|
|
600
|
+
API requests are throttled, and will fail with 429 error response.
|
|
601
|
+
|
|
602
|
+
No matter how many API keys you make in your Sendbee account,
|
|
603
|
+
rate limit will always be counted within a business number.
|
|
604
|
+
|
|
605
|
+
```python
|
|
606
|
+
from sendbee_api import SendbeeRequestApiException
|
|
607
|
+
|
|
608
|
+
try:
|
|
609
|
+
api.rate_limit_request_test()
|
|
610
|
+
except SendbeeRequestApiException as ex:
|
|
611
|
+
retry_after = ex.response.headers.get('Retry-After')
|
|
612
|
+
```
|
|
598
613
|
|
|
599
614
|
### <a href='#raw-response'>Raw response</a>
|
|
600
615
|
|
|
@@ -673,5 +688,3 @@ api = SendbeeApi(
|
|
|
673
688
|
Once you enabled the internal debug tool, every request to API will output various request and response data in standard output:
|
|
674
689
|
|
|
675
690
|

|
|
676
|
-
|
|
677
|
-
|
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
|
|
5
|
-
.' '. __
|
|
6
|
-
. . . (__\_
|
|
7
|
-
. . . -{{_(|8)
|
|
8
|
-
' . . ' ' . . ' (__/
|
|
9
|
-
|
|
10
|
-
```
|
|
1
|
+
# AI Number Python API Client
|
|
11
2
|
|
|
12
3
|
[](https://badge.fury.io/py/sendbee-api)
|
|
13
|
-
[](https://travis-ci.org/sendbee/sendbee-python-api-client)
|
|
14
|
-
|
|
15
|
-

|
|
16
|
-

|
|
17
|
-

|
|
18
|
-
|
|
19
|
-

|
|
20
|
-

|
|
21
|
-

|
|
22
4
|
|
|
23
5
|
## Table of contents
|
|
24
6
|
|
|
@@ -66,6 +48,7 @@
|
|
|
66
48
|
#### Mics
|
|
67
49
|
|
|
68
50
|
- [Pagination](#pagination)
|
|
51
|
+
- [API Rate Limit](#api-rate-limit)
|
|
69
52
|
- [Raw response](#raw-response)
|
|
70
53
|
- [Exception handling](#exception-handling)
|
|
71
54
|
- [Authenticate webhook request](#authenticate-webhook-request)
|
|
@@ -573,7 +556,25 @@ while True:
|
|
|
573
556
|
messages = api.messages(
|
|
574
557
|
conversation_id='...', page=messages.next_page()
|
|
575
558
|
)
|
|
576
|
-
```
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### <a href='#api-rate-limit'>API Rate Limit</a>
|
|
562
|
+
|
|
563
|
+
A rate limit is the number of API calls a business number can make
|
|
564
|
+
within a given time period. If this limit is exceeded,
|
|
565
|
+
API requests are throttled, and will fail with 429 error response.
|
|
566
|
+
|
|
567
|
+
No matter how many API keys you make in your Sendbee account,
|
|
568
|
+
rate limit will always be counted within a business number.
|
|
569
|
+
|
|
570
|
+
```python
|
|
571
|
+
from sendbee_api import SendbeeRequestApiException
|
|
572
|
+
|
|
573
|
+
try:
|
|
574
|
+
api.rate_limit_request_test()
|
|
575
|
+
except SendbeeRequestApiException as ex:
|
|
576
|
+
retry_after = ex.response.headers.get('Retry-After')
|
|
577
|
+
```
|
|
577
578
|
|
|
578
579
|
### <a href='#raw-response'>Raw response</a>
|
|
579
580
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sendbee_api"
|
|
7
|
+
version = "1.7.2"
|
|
8
|
+
description = "Python client SDK for Sendbee Public API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.6"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Sendbee ltd", email = "info@sendbee.io" }]
|
|
13
|
+
keywords = ["sendbee", "api", "python"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Topic :: Software Development :: Build Tools",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3.6",
|
|
19
|
+
"Programming Language :: Python :: 3.7",
|
|
20
|
+
"Programming Language :: Python :: 3.8",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"click>=7.0",
|
|
29
|
+
"requests>=2.20.0",
|
|
30
|
+
"dumpit>=0.5.0",
|
|
31
|
+
"aenum>=2.1.2",
|
|
32
|
+
"ujson>=5.7.0,<6",
|
|
33
|
+
"cryptography>=3.2",
|
|
34
|
+
"curlify>=2.2.1",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
dev = ["pytest", "responses>=0.23"]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/sendbee/sendbee-python-client"
|
|
42
|
+
Source = "https://github.com/sendbee/sendbee-python-client"
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.packages.find]
|
|
45
|
+
include = ["sendbee_api*"]
|
|
46
|
+
exclude = ["tests*"]
|
|
@@ -23,6 +23,9 @@ def bind_request(**request_data):
|
|
|
23
23
|
model = request_data.get(constants.ClientConst.MODEL)
|
|
24
24
|
api_path = request_data.get(constants.RequestConst.API_PATH)
|
|
25
25
|
formatter = request_data.get(constants.ClientConst.FORMATTER)
|
|
26
|
+
ignore_error = request_data.get(
|
|
27
|
+
constants.ClientConst.IGNORE_ERROR, False
|
|
28
|
+
)
|
|
26
29
|
method = request_data.get(
|
|
27
30
|
constants.RequestConst.METHOD, constants.RequestConst.GET
|
|
28
31
|
)
|
|
@@ -187,8 +190,12 @@ def bind_request(**request_data):
|
|
|
187
190
|
self.parameters[constants.RequestConst.QUERY]
|
|
188
191
|
)
|
|
189
192
|
self.debug.ok(constants.ResponseConst.RESPONSE_OBJECT, response)
|
|
193
|
+
self.debug.set_curl(
|
|
194
|
+
constants.DebugConst.CURL,
|
|
195
|
+
response.request
|
|
196
|
+
)
|
|
190
197
|
|
|
191
|
-
return response.status_code, response.text
|
|
198
|
+
return response.status_code, response.headers, response.text
|
|
192
199
|
|
|
193
200
|
elif self.method in [
|
|
194
201
|
constants.RequestConst.POST,
|
|
@@ -210,14 +217,20 @@ def bind_request(**request_data):
|
|
|
210
217
|
self.debug.ok('payload', self.parameters[
|
|
211
218
|
constants.RequestConst.QUERY
|
|
212
219
|
])
|
|
213
|
-
self.debug.ok(
|
|
220
|
+
self.debug.ok(
|
|
221
|
+
constants.ResponseConst.RESPONSE_OBJECT, response
|
|
222
|
+
)
|
|
223
|
+
self.debug.set_curl(
|
|
224
|
+
constants.DebugConst.CURL,
|
|
225
|
+
response.request
|
|
226
|
+
)
|
|
214
227
|
|
|
215
|
-
return response.status_code, response.text
|
|
228
|
+
return response.status_code, response.headers, response.text
|
|
216
229
|
|
|
217
230
|
else:
|
|
218
231
|
return constants.ResponseCode.NOT_FOUND, {}
|
|
219
232
|
|
|
220
|
-
def _process_response(self, status_code, response):
|
|
233
|
+
def _process_response(self, status_code, response, headers):
|
|
221
234
|
"""
|
|
222
235
|
Process response using models
|
|
223
236
|
:status_code: Response status code
|
|
@@ -230,10 +243,11 @@ def bind_request(**request_data):
|
|
|
230
243
|
formatter = FormatterFactory(constants.FormatterConst.JSON)\
|
|
231
244
|
.get_formatter()
|
|
232
245
|
|
|
233
|
-
response = Response(response, status_code, formatter, self)
|
|
246
|
+
response = Response(response, headers, status_code, formatter, self)
|
|
234
247
|
formatted_data = response.formatted_data
|
|
235
248
|
|
|
236
|
-
if status_code >= constants.ResponseCode.BAD_REQUEST
|
|
249
|
+
if status_code >= constants.ResponseCode.BAD_REQUEST and \
|
|
250
|
+
self.ignore_error is False:
|
|
237
251
|
|
|
238
252
|
if status_code == constants.ResponseCode.NOT_FOUND:
|
|
239
253
|
error_msg = \
|
|
@@ -242,12 +256,18 @@ def bind_request(**request_data):
|
|
|
242
256
|
error_msg = \
|
|
243
257
|
constants.ResponseConst.DEFAULT_ERROR_MESSAGE
|
|
244
258
|
else:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
259
|
+
try:
|
|
260
|
+
error_msg = formatted_data.get(
|
|
261
|
+
constants.ErrorConst.ERROR, {}
|
|
262
|
+
).get(
|
|
263
|
+
constants.ErrorConst.DETAIL,
|
|
264
|
+
constants.ErrorConst.UNRECOGNIZED_ERROR
|
|
265
|
+
)
|
|
266
|
+
except AttributeError:
|
|
267
|
+
error_msg = formatted_data.get(
|
|
268
|
+
constants.ErrorConst.DETAIL,
|
|
269
|
+
constants.ErrorConst.UNRECOGNIZED_ERROR
|
|
270
|
+
)
|
|
251
271
|
|
|
252
272
|
self.debug.error(
|
|
253
273
|
constants.ResponseConst.STATUS_CODE, status_code
|
|
@@ -255,7 +275,7 @@ def bind_request(**request_data):
|
|
|
255
275
|
self.debug.error(
|
|
256
276
|
constants.ResponseConst.RESPONSE, response.formatted_data
|
|
257
277
|
)
|
|
258
|
-
raise SendbeeRequestApiException(error_msg)
|
|
278
|
+
raise SendbeeRequestApiException(error_msg, response=response)
|
|
259
279
|
else:
|
|
260
280
|
self.debug.ok(constants.ResponseConst.STATUS_CODE, status_code)
|
|
261
281
|
self.debug.ok(constants.ResponseConst.RESPONSE, response.raw_data)
|
|
@@ -287,8 +307,8 @@ def bind_request(**request_data):
|
|
|
287
307
|
"""
|
|
288
308
|
|
|
289
309
|
self.url = self._prepare_url()
|
|
290
|
-
status_code, response = self._do_request(self.url)
|
|
291
|
-
return self._process_response(status_code, response)
|
|
310
|
+
status_code, headers, response = self._do_request(self.url)
|
|
311
|
+
return self._process_response(status_code, response, headers)
|
|
292
312
|
|
|
293
313
|
def call(client, *path_params, **query_params):
|
|
294
314
|
"""
|
|
@@ -3,12 +3,13 @@ import click
|
|
|
3
3
|
from sendbee_api.auth import SendbeeAuth
|
|
4
4
|
from sendbee_api.teams.client import Teams
|
|
5
5
|
from sendbee_api.contacts.client import Contacts
|
|
6
|
+
from sendbee_api.rate_limit.client import RateLimit
|
|
6
7
|
from sendbee_api.automation.client import Automation
|
|
7
8
|
from sendbee_api.conversations.client import Messages
|
|
8
9
|
from sendbee_api.exceptions import SendbeeRequestApiException
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
class Client(Contacts, Messages, Automation, Teams):
|
|
12
|
+
class Client(Contacts, Messages, Automation, Teams, RateLimit):
|
|
12
13
|
"""Main API class. Sets all API calls."""
|
|
13
14
|
|
|
14
15
|
base_url = 'api-v2.sendbee.io'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from abc import ABCMeta
|
|
1
2
|
from collections import namedtuple
|
|
2
3
|
|
|
3
4
|
|
|
@@ -38,9 +39,11 @@ ResponseConst = namedtuple(
|
|
|
38
39
|
|
|
39
40
|
ClientConst = namedtuple(
|
|
40
41
|
'ClientConst', [
|
|
41
|
-
'META', 'MODEL', 'MODELS', 'FORMATTER', 'DESCRIPTION',
|
|
42
|
+
'META', 'MODEL', 'MODELS', 'FORMATTER', 'DESCRIPTION',
|
|
43
|
+
'FORCE_SINGLE_MODEL_RESPONSE', 'IGNORE_ERROR', 'HEADERS'
|
|
42
44
|
]
|
|
43
|
-
)('meta', 'model', 'models', 'formatter', 'description',
|
|
45
|
+
)('meta', 'model', 'models', 'formatter', 'description',
|
|
46
|
+
'force_single_model_response', 'ignore_error', 'headers')
|
|
44
47
|
|
|
45
48
|
FormatterConst = namedtuple(
|
|
46
49
|
'FormatterConst', ['JSON', 'FORMATTED']
|
|
@@ -61,3 +64,24 @@ MiscConst = namedtuple(
|
|
|
61
64
|
ResponseDataConst = namedtuple(
|
|
62
65
|
'ResponseDataConst', ['DATA', 'META']
|
|
63
66
|
)('data', 'meta')
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ConstMeta(ABCMeta):
|
|
70
|
+
def __setattr__(self, name, value):
|
|
71
|
+
pass
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class Const(metaclass=ConstMeta):
|
|
75
|
+
"""Helper class """
|
|
76
|
+
__slots__ = ()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class DebugConst(Const):
|
|
80
|
+
PARAMETERS = 'parameters'
|
|
81
|
+
RESPONSE = 'response'
|
|
82
|
+
STATUS_CODE = 'status code'
|
|
83
|
+
FINAL_URL = 'final url'
|
|
84
|
+
HEADERS = 'headers'
|
|
85
|
+
METHOD = 'method'
|
|
86
|
+
QUERY_PARAMETERS = 'query parameters'
|
|
87
|
+
CURL = 'curl'
|
|
@@ -41,6 +41,8 @@ class SentMessage(Model):
|
|
|
41
41
|
|
|
42
42
|
_conversation_id = TextField(index='id', desc='Conversation UUID')
|
|
43
43
|
_message_id = TextField(index='message_id', desc='Message UUID')
|
|
44
|
+
_message_reference_id = TextField(index='message_reference_id',
|
|
45
|
+
desc='Message Reference UUID')
|
|
44
46
|
_status = TextField(index='status', desc='Message status')
|
|
45
47
|
|
|
46
48
|
|
|
@@ -21,6 +21,7 @@ class SendTemplateMessage(QueryParams):
|
|
|
21
21
|
prevent_bot_off = 'prevent_bot_off', 'Prevent turning-off chatbot'
|
|
22
22
|
agent_id = 'agent_id', 'Assigned agent for the conversation'
|
|
23
23
|
attachment = 'attachment', 'Attachment URL for media templates'
|
|
24
|
+
live_inbox = 'live_inbox', 'Trigger real-time events after sending'
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class SendMessage(QueryParams):
|
|
@@ -31,6 +32,7 @@ class SendMessage(QueryParams):
|
|
|
31
32
|
media_url = 'media_url', 'Media URL for media message'
|
|
32
33
|
prevent_bot_off = 'prevent_bot_off', 'Prevent turning-off chatbot'
|
|
33
34
|
agent_id = 'agent_id', 'Assigned agent for the conversation'
|
|
35
|
+
live_inbox = 'live_inbox', 'Trigger real-time events after sending'
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
class ListConversations(QueryParams):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import click
|
|
2
|
-
import
|
|
2
|
+
import curlify
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
STATUS_OK = 'ok'
|
|
@@ -25,6 +25,13 @@ class Debug:
|
|
|
25
25
|
def error(self, key, value):
|
|
26
26
|
self.record(key, value, STATUS_ERROR)
|
|
27
27
|
|
|
28
|
+
def set_curl(self, key, request):
|
|
29
|
+
if self.client.debug:
|
|
30
|
+
try:
|
|
31
|
+
self.ok(key, curlify.to_curl(request, compressed=False))
|
|
32
|
+
except UnicodeDecodeError:
|
|
33
|
+
self.ok(key, '__unable_to_decode__')
|
|
34
|
+
|
|
28
35
|
def record(self, key, value, status):
|
|
29
36
|
if self.client.debug:
|
|
30
37
|
self.recorded_data[key] = {'value': value, 'status': status}
|
|
@@ -29,6 +29,12 @@ class Formatter(metaclass=ABCMeta):
|
|
|
29
29
|
|
|
30
30
|
return data
|
|
31
31
|
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def _format_headers(self, data):
|
|
34
|
+
"""Format method in formatter classes."""
|
|
35
|
+
|
|
36
|
+
return data
|
|
37
|
+
|
|
32
38
|
def format_data(self, data):
|
|
33
39
|
"""Main format method."""
|
|
34
40
|
|
|
@@ -44,6 +50,11 @@ class Formatter(metaclass=ABCMeta):
|
|
|
44
50
|
|
|
45
51
|
return self._format_warning(data)
|
|
46
52
|
|
|
53
|
+
def format_headers(self, data):
|
|
54
|
+
"""Main format method."""
|
|
55
|
+
|
|
56
|
+
return self._format_headers(data)
|
|
57
|
+
|
|
47
58
|
@staticmethod
|
|
48
59
|
def _default_meta_data(total_results):
|
|
49
60
|
"""Create default data set if there aren't one from the response."""
|
|
@@ -106,6 +117,11 @@ class Json(Formatter):
|
|
|
106
117
|
if isinstance(formatted_data, dict):
|
|
107
118
|
return formatted_data.get(constants.WarningConst.WARNING)
|
|
108
119
|
|
|
120
|
+
def _format_headers(self, data):
|
|
121
|
+
"""Transform raw data from server into python native type."""
|
|
122
|
+
|
|
123
|
+
return data
|
|
124
|
+
|
|
109
125
|
|
|
110
126
|
class FormatterFactory:
|
|
111
127
|
"""Formatter factory class."""
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from sendbee_api import constants
|
|
2
|
+
from sendbee_api.bind import bind_request
|
|
3
|
+
from sendbee_api.rate_limit import query_params
|
|
4
|
+
from sendbee_api.rate_limit.models import RateLimitError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class RateLimit:
|
|
8
|
+
"""Api client for rete limit testing"""
|
|
9
|
+
|
|
10
|
+
rate_limit_error_test = bind_request(
|
|
11
|
+
api_path='/rate-limit/error-test',
|
|
12
|
+
model=RateLimitError,
|
|
13
|
+
query_parameters=query_params.RateLimitParams,
|
|
14
|
+
method=constants.RequestConst.GET,
|
|
15
|
+
# ignore_error=True,
|
|
16
|
+
description='Rate limit error test'
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
rate_limit_request_test = bind_request(
|
|
20
|
+
api_path='/rate-limit/request-test',
|
|
21
|
+
model=RateLimitError,
|
|
22
|
+
query_parameters=query_params.RateLimitParams,
|
|
23
|
+
method=constants.RequestConst.GET,
|
|
24
|
+
# ignore_error=True,
|
|
25
|
+
description='Rate limit request test'
|
|
26
|
+
)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from sendbee_api.models import Model
|
|
2
|
+
from sendbee_api.fields import TextField, BooleanField
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class RateLimitError(Model):
|
|
6
|
+
"""Data model for rate limit error"""
|
|
7
|
+
|
|
8
|
+
_detail = TextField(index='detail', desc='Message detail')
|
|
9
|
+
_error = BooleanField(index='error', desc='Error or not')
|
|
10
|
+
_type = TextField(index='type', desc='Message type')
|
|
@@ -4,8 +4,9 @@ from sendbee_api import constants
|
|
|
4
4
|
class Response:
|
|
5
5
|
"""Response object returned from API call."""
|
|
6
6
|
|
|
7
|
-
def __init__(self, data, status_code, formatter, api_request):
|
|
7
|
+
def __init__(self, data, headers, status_code, formatter, api_request):
|
|
8
8
|
self._data = data
|
|
9
|
+
self._headers = headers
|
|
9
10
|
self._model = api_request.model
|
|
10
11
|
|
|
11
12
|
self.api_reguest = api_request
|
|
@@ -16,7 +17,8 @@ class Response:
|
|
|
16
17
|
constants.FormatterConst.FORMATTED: None,
|
|
17
18
|
constants.ClientConst.MODELS: None,
|
|
18
19
|
constants.ClientConst.META: None,
|
|
19
|
-
constants.WarningConst.WARNING: None
|
|
20
|
+
constants.WarningConst.WARNING: None,
|
|
21
|
+
constants.ClientConst.HEADERS: None,
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
def __iter__(self):
|
|
@@ -63,6 +65,16 @@ class Response:
|
|
|
63
65
|
|
|
64
66
|
return self._response_data[constants.ClientConst.META]
|
|
65
67
|
|
|
68
|
+
@property
|
|
69
|
+
def headers(self):
|
|
70
|
+
"""Response headers."""
|
|
71
|
+
|
|
72
|
+
if not self._response_data[constants.ClientConst.HEADERS]:
|
|
73
|
+
self._response_data[constants.ClientConst.HEADERS] = \
|
|
74
|
+
self.formatter.format_headers(self._headers)
|
|
75
|
+
|
|
76
|
+
return self._response_data[constants.ClientConst.HEADERS]
|
|
77
|
+
|
|
66
78
|
@property
|
|
67
79
|
def warning(self):
|
|
68
80
|
"""Format warning data using selected formatter."""
|
|
File without changes
|