Skip to content
This repository was archived by the owner on Sep 6, 2025. It is now read-only.

Commit 5b074d1

Browse files
authored
Merge pull request #21 from hellofresh/feature/opt-out
Add crossengage opt-out endpoints
2 parents 71b7c20 + da57b7a commit 5b074d1

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

crossengage/client.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class CrossengageClient(object):
5555
USER_BULK_ENDPOINT = "{0}/batch".format(USER_ENDPOINT)
5656
TRACK_USER_TASK_ENDPOINT = "{0}/track".format(USER_ENDPOINT)
5757
EVENTS_ENDPOINT = 'events'
58+
OPTOUT_ENDPOINT = 'optout-status'
5859

5960
REQUEST_GET = 'get'
6061
REQUEST_PUT = 'put'
@@ -350,6 +351,36 @@ def track_user_task(self, tracking_id):
350351

351352
return r.status_code, body
352353

354+
def get_user_opt_out_status(self, user_id):
355+
# type: (str) -> dict
356+
"""
357+
Fetch User Opt-Out status by id.
358+
:param user_id: User external ID
359+
:return: json dict response, for example:
360+
{
361+
"optOut": false
362+
}
363+
"""
364+
self.request_url = "{0}/{1}/{2}/{3}".format(self.API_URL, self.USER_ENDPOINT, user_id, self.OPTOUT_ENDPOINT)
365+
return self.__create_request(payload={}, request_type=self.REQUEST_GET, version="v1")
366+
367+
def update_user_opt_out_status(self, user_id, channel_name):
368+
# type: (str, str) -> dict
369+
"""
370+
Fetch User Opt-Out status by id.
371+
:param user_id: User ID
372+
:param channel_name: Name of the channel to opt out user from. It has to be one of MAIL, BROWSER_NOTIFICATION,
373+
ONSITE_DISPLAY, EXIT_INTENT, PUSH_NOTIFICATION, DIRECT_MAIL or SMS
374+
:return: json dict response, for example:
375+
{
376+
"optOut": true
377+
}
378+
"""
379+
self.request_url = "{0}/{1}/{2}/{3}?channelType={4}".format(
380+
self.API_URL, self.USER_ENDPOINT, user_id, self.OPTOUT_ENDPOINT, channel_name
381+
)
382+
return self.__create_request(payload={"optOut": True}, request_type=self.REQUEST_PUT, version="v1")
383+
353384
def __create_request(self, payload, request_type, version):
354385
headers = update_dict(self.default_headers, {self.API_VERSION_HEADER: self.API_VERSIONS[version]})
355386
try:

tests/test_client.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def setUp(self):
5656
'birthday': '1991-11-07',
5757
'createdAt': '2015-10-02T08:23:53Z',
5858
'gender': 'male',
59+
'channel': 'MAIL'
5960
}
6061
self.default_headers_api_v1 = {
6162
'X-XNG-AuthToken': 'SOME_TOKEN',
@@ -625,3 +626,56 @@ def test_track_user_task_not_found(self):
625626
)
626627

627628
self.assertEqual(result, (codes.not_found, None))
629+
630+
def test_get_user_opt_out_status(self):
631+
"""Crossengage returns status code 200"""
632+
# GIVEN
633+
expected_response = self.user.copy()
634+
expected_response.update({"status_code": codes.ok})
635+
response = Mock(status_code=codes.ok)
636+
response.json.return_value = expected_response
637+
requests = Mock()
638+
requests.get.return_value = response
639+
640+
requests = Mock()
641+
requests.get.return_value = response
642+
self.client.requests = requests
643+
644+
# WHEN
645+
result = self.client.get_user_opt_out_status(self.user['id'])
646+
647+
# THEN
648+
requests.get.assert_called_once_with(
649+
self.CROSSENGAGE_URL + 'users/1234/optout-status',
650+
headers=self.default_headers_api_v1,
651+
timeout=30
652+
)
653+
654+
self.assertEqual(expected_response, result)
655+
656+
def test_update_user_opt_out_status(self):
657+
"""Crossengage returns status code 200"""
658+
# GIVEN
659+
expected_response = self.user.copy()
660+
expected_response.update({"status_code": codes.ok})
661+
response = Mock(status_code=codes.ok)
662+
response.json.return_value = expected_response
663+
requests = Mock()
664+
requests.get.return_value = response
665+
666+
requests = Mock()
667+
requests.put.return_value = response
668+
self.client.requests = requests
669+
670+
# WHEN
671+
result = self.client.update_user_opt_out_status(self.user['id'], self.user['channel'])
672+
673+
# THEN
674+
requests.put.assert_called_once_with(
675+
self.CROSSENGAGE_URL + 'users/1234/optout-status?channelType=' + self.user['channel'],
676+
data='{"optOut": true}',
677+
headers=self.default_headers_api_v1,
678+
timeout=30
679+
)
680+
681+
self.assertEqual(expected_response, result)

0 commit comments

Comments
 (0)