diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ccc27fe..c861e27c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## [4.45.0](https://github.com/plivo/plivo-python/tree/v4.45.0) (2023-11-03) +**Feature - TollFree Verification API Support** +- API support for Create, Update, Get, Delete and List Tollfree Verification. +- Added New Param `toll_free_sms_verification_id` and `toll_free_sms_verification_order_status `in to the response of the [list all numbers API], [list single number API] +- Added `toll_free_sms_verification_order_status` filter to AccountPhoneNumber - list all my numbers API. + ## [4.44.0](https://github.com/plivo/plivo-python/tree/v4.44.0) (2023-10-18) **Feature - Fixes for Campaign services list API meta data** - Fixed Meta data response for campaign, brand and profile list diff --git a/plivo/base.py b/plivo/base.py index 5378e0a0..393fe809 100644 --- a/plivo/base.py +++ b/plivo/base.py @@ -151,6 +151,42 @@ def __str__(self): def __repr__(self): return str([object for object in self.objects]) +class ListTollfreeVerificationResponseObject(ResponseObject): + def __init__(self, client, dct): + super(ListTollfreeVerificationResponseObject, self).__init__(dct) + self.error = dct.get('error', None) + self.objects = dct.get('objects', []) + self.meta = dct.get('meta', None) + self.apiID = dct.get('api_id', None) + + def __iter__(self): + if self.objects is not None: + return self.objects.__iter__() + else: + return iter([]) + + def __len__(self): + if self.objects is not None: + return len(self.objects) + else: + return 0 # Return 0 for error case + + def __str__(self): + if self.objects is not None: + response_dict = {'api_id': self.apiID, 'meta': self.meta, 'objects': self.objects} + return pprint.pformat(response_dict) + else: + return str(self.error) # Display error message for error case + + def __repr__(self): + if self.objects is not None: + response_dict = {'api_id': self.apiID, 'meta': self.meta, 'objects': [session for session in self.objects]} + return str(response_dict) + else: + return str(self.error) # Display error message for error case + + def has_error(self): + return self.error is not None class PlivoResource(ResponseObject): """The Plivo resource object diff --git a/plivo/resources/__init__.py b/plivo/resources/__init__.py index 6850f5a2..49fa1d62 100644 --- a/plivo/resources/__init__.py +++ b/plivo/resources/__init__.py @@ -21,3 +21,4 @@ from .profile import Profile from .multipartycall import MultiPartyCalls, MultiPartyCall, MultiPartyCallParticipant from .verify import Sessions +from .tollfree_verification import TollfreeVerifications diff --git a/plivo/resources/numbers.py b/plivo/resources/numbers.py index c676dbef..9549f5b8 100644 --- a/plivo/resources/numbers.py +++ b/plivo/resources/numbers.py @@ -90,6 +90,7 @@ def list(self, renewal_date__gte=None, renewal_date__gt=None, cnam_lookup=None, + toll_free_sms_verification_order_status=None, limit=20, offset=0): return self.client.request( diff --git a/plivo/resources/tollfree_verification.py b/plivo/resources/tollfree_verification.py new file mode 100644 index 00000000..cb90133d --- /dev/null +++ b/plivo/resources/tollfree_verification.py @@ -0,0 +1,90 @@ +from ..utils.validators import * + +from ..base import PlivoResource, PlivoResourceInterface, ListTollfreeVerificationResponseObject +from ..exceptions import * +from ..utils import * + + +class TollfreeVerification(PlivoResource): + _name = 'TollfreeVerification' + _identifier_string = 'uuid' + + def delete(self): + return self.client.tollfree_verification.delete(tollfree_verification_uuid=self.uuid) + + def update(self, + profile_uuid=None, + usecase=None, + usecase_summary=None, + message_sample=None, + optin_image_url=None, + volume=None, + additional_information=None, + extra_data=None, + optin_type=None, + callback_url=None, + callback_method=None): + return self.client.tollfree_verification.update(self.uuid, profile_uuid=profile_uuid, usecase=usecase, + usecase_summary=usecase_summary, message_sample=message_sample, + optin_image_url=optin_image_url, volume=volume, + additional_information=additional_information, + extra_data=extra_data, optin_type=optin_type, + callback_url=callback_url, callback_method=callback_method) + +class TollfreeVerifications(PlivoResourceInterface): + def __init__(self, client): + self._resource_type = TollfreeVerification + super(TollfreeVerifications, self).__init__(client) + + def create(self, + profile_uuid=None, + usecase=None, + usecase_summary=None, + message_sample=None, + optin_image_url=None, + volume=None, + number=None, + additional_information=None, + extra_data=None, + optin_type=None, + callback_url=None, + callback_method=None): + return self.client.request( + 'POST', ('TollfreeVerification',), to_param_dict(self.create, locals())) + + def get(self, tollfree_verification_uuid=None): + return self.client.request( + 'GET', ('TollfreeVerification', tollfree_verification_uuid), response_type=TollfreeVerification) + + def list(self, + number=None, + status=None, + profile_uuid=None, + created__gt=None, + created__gte=None, + created__lt=None, + created__lte=None, + usecase=None, + limit=20, + offset=0): + return self.client.request( + 'GET', ('TollfreeVerification',), to_param_dict(self.list, locals()), + objects_type=TollfreeVerification, response_type=ListTollfreeVerificationResponseObject, ) + + def update(self, tollfree_verification_uuid=None, + profile_uuid=None, + usecase=None, + usecase_summary=None, + message_sample=None, + optin_image_url=None, + volume=None, + additional_information=None, + extra_data=None, + optin_type=None, + callback_url=None, + callback_method=None): + return self.client.request( + 'POST', ('TollfreeVerification', tollfree_verification_uuid), to_param_dict(self.update, locals())) + + def delete(self, tollfree_verification_uuid=None): + return self.client.request('DELETE', ('TollfreeVerification', tollfree_verification_uuid)) diff --git a/plivo/rest/client.py b/plivo/rest/client.py index ce459cf6..19c2f24e 100644 --- a/plivo/rest/client.py +++ b/plivo/rest/client.py @@ -14,7 +14,8 @@ from plivo.resources import (Accounts, Addresses, Applications, Calls, Token, Conferences, Endpoints, Identities, Messages, Powerpacks, Media, Lookup, Brand, Campaign, Profile, - Numbers, Pricings, Recordings, Subaccounts, CallFeedback, MultiPartyCalls, Sessions) + Numbers, Pricings, Recordings, Subaccounts, CallFeedback, MultiPartyCalls, Sessions, + TollfreeVerifications) from plivo.resources.live_calls import LiveCalls from plivo.resources.maskingsession import MaskingSessions from plivo.resources.verify_callerid import VerifyCallerids @@ -101,6 +102,7 @@ def __init__(self, auth_id=None, auth_token=None, proxies=None, timeout=5): self.messages = Messages(self) self.lookup = Lookup(self) self.numbers = Numbers(self) + self.tollfree_verification = TollfreeVerifications(self) self.powerpacks = Powerpacks(self) self.brand = Brand(self) self.campaign = Campaign(self) diff --git a/plivo/version.py b/plivo/version.py index 24ef7fee..d4c3ccd3 100644 --- a/plivo/version.py +++ b/plivo/version.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -__version__ = '4.44.0' +__version__ = '4.45.0' diff --git a/setup.py b/setup.py index 866b7447..8f5f0cbd 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( name='plivo', - version='4.44.0', + version='4.45.0', description='A Python SDK to make voice calls & send SMS using Plivo and to generate Plivo XML', long_description=long_description, url='https://github.com/plivo/plivo-python', diff --git a/tests/resources/fixtures/tollfreeVerificationCreateResponse.json b/tests/resources/fixtures/tollfreeVerificationCreateResponse.json new file mode 100644 index 00000000..2e389841 --- /dev/null +++ b/tests/resources/fixtures/tollfreeVerificationCreateResponse.json @@ -0,0 +1,5 @@ +{ + "api_id": "5a9fcb68-582d-11e1-86da-6ff39efcb949", + "message": "Tollfree verification request for 18339404937 submitted succesfully", + "uuid": "f19c4773-4ae6-4b75-92ea-9cf3ea4227d6" +} \ No newline at end of file diff --git a/tests/resources/fixtures/tollfreeVerificationGetResponse.json b/tests/resources/fixtures/tollfreeVerificationGetResponse.json new file mode 100644 index 00000000..6205805f --- /dev/null +++ b/tests/resources/fixtures/tollfreeVerificationGetResponse.json @@ -0,0 +1,20 @@ +{ + "api_id": "4e1f954c-baf3-11ec-bafe-0242ac110003", + "additional_information": "", + "callback_method": "POST", + "callback_url": "http://plivobin-prod-usw1.plivops.com/1e4jvpt1", + "created": "2023-10-12T15:28:10.216507Z", + "extra_data": "", + "message_sample": "1.Your Plivo verification code is xxxx. 2.Dear , you have signed up on Plivo successfully.", + "number": "18449605287", + "optin_image_url": "https://www.plivo.com", + "optin_type": "MOBILE_QR_CODE", + "profile_uuid": "0ead82e0-fc80-4dc3-888b-7778932cf134", + "error_message": "Demo Testing Sanity", + "status": "REJECTED", + "last_modified": "2023-10-13T08:24:26.619565Z", + "usecase": "2FA", + "usecase_summary": "1.We send 2FA codes to customers when they signup. 2.Dear , you have signed up on Plivo successfully.", + "uuid": "312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX", + "volume": "100" +} \ No newline at end of file diff --git a/tests/resources/fixtures/tollfreeVerificationListResponse.json b/tests/resources/fixtures/tollfreeVerificationListResponse.json new file mode 100644 index 00000000..37a7f496 --- /dev/null +++ b/tests/resources/fixtures/tollfreeVerificationListResponse.json @@ -0,0 +1,50 @@ +{ + "api_id": "4e15f360-72fe-11ee-8538-e20bbbfb283e", + "meta": { + "count": 2, + "limit": 10, + "next": null, + "offset": 10, + "previous": "/v1/Account/MAXXXXXXXXXXXXXXXXXX/TollfreeVerification/?limit=10&offset=0" + }, + "objects": [ + { + "additional_information": "", + "callback_method": "POST", + "callback_url": "http://plivobin-prod-usw1.plivops.com/1e4jvpt1", + "created": "2023-10-12T15:28:10.216507Z", + "extra_data": "", + "message_sample": "1.Your Plivo verification code is xxxx. 2.Dear , you have signed up on Plivo successfully.", + "number": "18449605287", + "optin_image_url": "https://www.plivo.com", + "optin_type": "MOBILE_QR_CODE", + "profile_uuid": "0ead82e0-fc80-4dc3-888b-7778932cf134", + "error_message": "Demo Testing Sanity", + "status": "REJECTED", + "last_modified": "2023-10-13T08:24:26.619565Z", + "usecase": "2FA", + "usecase_summary": "1.We send 2FA codes to customers when they signup. 2.Dear , you have signed up on Plivo successfully.", + "uuid": "312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX", + "volume": "100" + }, + { + "additional_information": "", + "callback_method": "POST", + "callback_url": "http://plivobin-prod-usw1.plivops.com/1e4jvpt1", + "created": "2023-10-12T12:06:46.527653Z", + "extra_data": "", + "message_sample": "1.Your Plivo verification code is xxxx. 2.Dear , you have signed up on Plivo successfully.", + "number": "18449605287", + "optin_image_url": "https://www.plivo.com", + "optin_type": "MOBILE_QR_CODE", + "profile_uuid": "0ead82e0-fc80-4dc3-888b-7778932cf134", + "error_message": "Demo Testing Sanity", + "status": "REJECTED", + "last_modified": "2023-10-12T15:27:56.052433Z", + "usecase": "2FA", + "usecase_summary": "1.We send 2FA codes to customers when they signup. 2.Dear , you have signed up on Plivo successfully.", + "uuid": "96ec880d-b7ee-4eb5-7c9a-3ff28826e77c", + "volume": "100" + } + ] +} \ No newline at end of file diff --git a/tests/resources/fixtures/tollfreeVerificationUpdateResponse.json b/tests/resources/fixtures/tollfreeVerificationUpdateResponse.json new file mode 100644 index 00000000..01e020ab --- /dev/null +++ b/tests/resources/fixtures/tollfreeVerificationUpdateResponse.json @@ -0,0 +1,4 @@ +{ + "api_id": "4e1f954c-baf3-11ec-bafe-0242ac110003", + "message": "Tollfree verification request for 18339404937 updated succesfully" +} \ No newline at end of file diff --git a/tests/resources/test_tollfree_verification.py b/tests/resources/test_tollfree_verification.py new file mode 100644 index 00000000..f1d59c8b --- /dev/null +++ b/tests/resources/test_tollfree_verification.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- + +import plivo +from tests.base import PlivoResourceTestCase +from tests.decorators import with_response + + +class TollfreeVerificationTest(PlivoResourceTestCase): + @with_response(200) + def test_list(self): + tollfree_verification = self.client.tollfree_verification.list(offset=10, limit=10) + + # Verifying the endpoint hit + self.assertUrlEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/TollfreeVerification/?limit=10&offset=10', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('GET', self.client.current_request.method) + + self.assertEqual('312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX', tollfree_verification.objects[0].uuid) + + # Test if ListResponseObject's __iter__ is working correctly + self.assertEqual(len(list(tollfree_verification)), 2) + + + @with_response(200) + def test_get(self): + tollfree_verficiation = self.client.tollfree_verification.get( + tollfree_verification_uuid="312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX") + + self.assertResponseMatches(tollfree_verficiation) + + # Verifying the endpoint hit + self.assertEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/TollfreeVerification/312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX/', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('GET', self.client.current_request.method) + + # Verifying the object type returned + self.assertEqual(plivo.resources.tollfree_verification.TollfreeVerification, + tollfree_verficiation.__class__) + + self.assertEqual('312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX', tollfree_verficiation.uuid) + + @with_response(202) + def test_update(self): + updated_app = self.client.tollfree_verification.update( + tollfree_verification_uuid="312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX", + extra_data='Testing the update of extra data in python-SDK') + + # Verifying the endpoint hit + self.assertEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/TollfreeVerification/312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX/', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('POST', self.client.current_request.method) + + def test_delete(self): + expected_response = {} + + self.client.set_expected_response( + status_code=204, data_to_return=expected_response) + + response = self.client.tollfree_verification.delete( + tollfree_verification_uuid="312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX") + + # Verifying the endpoint hit + self.assertEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/TollfreeVerification/312b3119-XXXX-XXXX-XXXX-XXXXXXXXXXXX/', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('DELETE', self.client.current_request.method) + + @with_response(201) + def test_create(self): + response = self.client.tollfree_verification.create( + usecase="2FA", + number="18554950186", + profile_uuid="42f92135-6ec2-4110-8da4-71171f6aad44", + optin_type="VERBAL", + volume="100", + usecase_summary="hbv", + message_sample="message_sample", + callback_url="https://plivobin-prod-usw1.plivops.com/1pcfjrt1", + callback_method="POST", + optin_image_url="http://aaa.com", + additional_information="this is additional_information", + extra_data="this is extra_data", + ) + + # Verifying the endpoint hit + self.assertEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/TollfreeVerification/', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('POST', self.client.current_request.method)