Skip to content

Commit 0037d0c

Browse files
committed
Support transactional inbox messages
1 parent 0baf6ed commit 0037d0c

4 files changed

Lines changed: 81 additions & 4 deletions

File tree

customerio/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
from customerio.client_base import CustomerIOException
44
from customerio.track import CustomerIO
5-
from customerio.api import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest
5+
from customerio.api import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest
66
from customerio.regions import Regions

customerio/api.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ def send_sms(self, request):
3434
resp = self.send_request('POST', self.url + "/v1/send/sms", request)
3535
return json.loads(resp)
3636

37+
def send_inbox_message(self, request):
38+
if isinstance(request, SendInboxMessageRequest):
39+
request = request._to_dict()
40+
resp = self.send_request('POST', self.url + "/v1/send/inbox_message", request)
41+
return json.loads(resp)
42+
3743
# builds the session.
3844
def _build_session(self):
3945
session = super()._build_session()
@@ -219,7 +225,7 @@ def _to_dict(self):
219225
return data
220226

221227
class SendSMSRequest(object):
222-
'''An object with all the options avaiable for triggering a transactional push message'''
228+
'''An object with all the options avaiable for triggering a transactional SMS message'''
223229
def __init__(self,
224230
transactional_message_id=None,
225231
to=None,
@@ -264,3 +270,44 @@ def _to_dict(self):
264270
data[name] = value
265271

266272
return data
273+
274+
class SendInboxMessageRequest(object):
275+
'''An object with all the options avaiable for triggering a transactional inbox message'''
276+
def __init__(self,
277+
transactional_message_id=None,
278+
identifiers=None,
279+
disable_message_retention=None,
280+
queue_draft=None,
281+
message_data=None,
282+
send_at=None,
283+
language=None,
284+
):
285+
286+
self.transactional_message_id = transactional_message_id
287+
self.identifiers = identifiers
288+
self.disable_message_retention = disable_message_retention
289+
self.queue_draft = queue_draft
290+
self.message_data = message_data
291+
self.send_at = send_at
292+
self.language = language
293+
294+
def _to_dict(self):
295+
'''Build a request payload from the object'''
296+
field_map = dict(
297+
# field name is the same as the payload field name
298+
transactional_message_id="transactional_message_id",
299+
identifiers="identifiers",
300+
disable_message_retention="disable_message_retention",
301+
queue_draft="queue_draft",
302+
message_data="message_data",
303+
send_at="send_at",
304+
language="language",
305+
)
306+
307+
data = {}
308+
for field, name in field_map.items():
309+
value = getattr(self, field, None)
310+
if value is not None:
311+
data[name] = value
312+
313+
return data

tests/server.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ def create_ssl_context():
1414
"""Create SSL context for Python 3.12+ compatibility"""
1515
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1616
context.minimum_version = ssl.TLSVersion.TLSv1_2
17+
# Disable hostname and certificate verification for self-signed certs
18+
context.check_hostname = False
19+
context.verify_mode = ssl.CERT_NONE
20+
# Allow weaker ciphers for test compatibility
21+
try:
22+
context.set_ciphers('DEFAULT@SECLEVEL=1')
23+
except ssl.SSLError:
24+
# Fall back if the cipher string is not supported
25+
pass
1726
return context
1827

1928
request_counts = dict()
@@ -28,12 +37,16 @@ class Handler(BaseHTTPRequestHandler):
2837
'''
2938
def do_DELETE(self):
3039
self.send_response(200)
40+
self.send_header('Content-Length', '0')
3141
self.end_headers()
3242

3343
def do_POST(self):
44+
response_body = bytes("{}", "utf-8")
3445
self.send_response(200)
46+
self.send_header('Content-Type', 'application/json')
47+
self.send_header('Content-Length', str(len(response_body)))
3548
self.end_headers()
36-
self.wfile.write(bytes("{}", "utf-8"))
49+
self.wfile.write(response_body)
3750

3851
def do_PUT(self):
3952
global request_counts
@@ -49,6 +62,7 @@ def do_PUT(self):
4962
if processed > fail_count:
5063
# return a valid response
5164
self.send_response(200)
65+
self.send_header('Content-Length', '0')
5266
self.end_headers()
5367
return
5468

tests/test_api.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import sys
66
import unittest
77

8-
from customerio import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, Regions, CustomerIOException
8+
from customerio import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, SendInboxMessageRequest, Regions, CustomerIOException
99
from customerio.__version__ import __version__ as ClientVersion
1010
from tests.server import HTTPSTestCase
1111

@@ -111,5 +111,21 @@ def test_send_sms(self):
111111

112112
self.client.send_sms(sms)
113113

114+
def test_send_inbox_message(self):
115+
self.client.http.hooks = dict(response=partial(self._check_request, rq={
116+
'method': 'POST',
117+
'authorization': "Bearer app_api_key",
118+
'content_type': 'application/json',
119+
'url_suffix': '/v1/send/inbox_message',
120+
'body': {"identifiers": {"id":"customer_1"}, "transactional_message_id": 100}
121+
}))
122+
123+
inbox_message = SendInboxMessageRequest(
124+
identifiers={"id":"customer_1"},
125+
transactional_message_id=100,
126+
)
127+
128+
self.client.send_inbox_message(inbox_message)
129+
114130
if __name__ == '__main__':
115131
unittest.main()

0 commit comments

Comments
 (0)