Skip to content

Commit 53daec5

Browse files
Stefan RoginStefan Rogin
Stefan Rogin
authored and
Stefan Rogin
committed
add method for creating call
1 parent 9d040c6 commit 53daec5

File tree

6 files changed

+239
-36
lines changed

6 files changed

+239
-36
lines changed

examples/call.py

+26-30
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,42 @@
11
#!/usr/bin/env python
22

3-
import sys, os
3+
import os
4+
import sys
5+
46
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
57

68
import messagebird
79

8-
#ACCESS_KEY = ''
9-
#CALL_ID = ''
10+
# ACCESS_KEY = ''
11+
# CALL_ID = ''
1012

1113
try:
12-
ACCESS_KEY
14+
ACCESS_KEY
1315
except NameError:
14-
print('You need to set an ACCESS_KEY constant in this file')
15-
sys.exit(1)
16+
print('You need to set an ACCESS_KEY constant in this file')
17+
sys.exit(1)
1618

1719
try:
18-
CALL_ID
20+
CALL_ID
1921
except NameError:
20-
print('You need to set a CALL_ID constant in this file')
21-
sys.exit(1)
22+
print('You need to set a CALL_ID constant in this file')
23+
sys.exit(1)
2224

2325
try:
24-
# Create a MessageBird client with the specified ACCESS_KEY.
25-
client = messagebird.Client(ACCESS_KEY)
26-
27-
# Fetch the Message object for the specified MESSAGE_ID.
28-
call = client.call(CALL_ID)
29-
30-
# Print the object information.
31-
print('\nThe following information was returned as a Message object:\n')
32-
print(' id : %s' % call.data.id)
33-
print(' status : %s' % call.data.status)
34-
print(' source : %s' % call.data.source)
35-
print(' destination : %s' % call.data.destination)
36-
print(' createdAt : %s' % call.data.createdAt)
37-
print(' updatedAt : %s' % call.data.updatedAt)
38-
print(' endedAt : %s' % call.data.endedAt)
39-
26+
# Create a MessageBird client with the specified ACCESS_KEY.
27+
client = messagebird.Client(ACCESS_KEY)
28+
29+
# Fetch the Call object for the specified CALL_ID.
30+
call = client.call(CALL_ID)
31+
32+
# Print the object information.
33+
print('\nThe following information was returned as a', str(call.__class__), 'object:\n')
34+
print(' '.join(str(call).splitlines(True)))
35+
4036
except messagebird.client.ErrorException as e:
41-
print('\nAn error occured while requesting a Message object:\n')
37+
print('\nAn error occurred while requesting a Message object:\n')
4238

43-
for error in e.errors:
44-
print(' code : %d' % error.code)
45-
print(' description : %s' % error.description)
46-
print(' parameter : %s\n' % error.parameter)
39+
for error in e.errors:
40+
print(' code : %d' % error.code)
41+
print(' description : %s' % error.description)
42+
print(' parameter : %s\n' % error.parameter)

examples/call_create.py

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python
2+
import os
3+
import sys
4+
import json
5+
import argparse
6+
import requests
7+
8+
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
9+
import messagebird
10+
11+
exampleCallFlow = '{"title":"Test Flow","steps":[{"action":"say","options":{"payload":"Hey, this is your first voice \
12+
call","language":"en-GB","voice":"female"}}]}'
13+
14+
parser = argparse.ArgumentParser(usage='call_create.py\
15+
--accessKey="*******" \
16+
--destination=31612345678 \
17+
--source=31644556677 \
18+
--callFlow \'' + exampleCallFlow + '\'\
19+
')
20+
parser.add_argument('--accessKey', help='access key for MessageBird API', type=str, required=True)
21+
parser.add_argument('--source', help='The caller ID of the call.', type=str, required=True)
22+
parser.add_argument('--destination', help='The number/address to be called.', type=str, required=True)
23+
parser.add_argument('--callFlow', help='The call flow object to be executed when the call is answered.', type=str, required=False, default=exampleCallFlow)
24+
parser.add_argument('--webhook', help='The webhook object containing the url & required token.', type=str, required=False, default='{}')
25+
args = vars(parser.parse_args())
26+
27+
# arguments to parse as json
28+
jsonArgs = ['callFlow', 'webhook']
29+
30+
print()
31+
for jsonArg in jsonArgs:
32+
try:
33+
args[jsonArg] = json.loads(str(args[jsonArg]).strip('\''))
34+
except json.decoder.JSONDecodeError as e:
35+
parser.print_usage()
36+
print('Invalid json provided for', jsonArg, ':', e)
37+
print('Provided', jsonArg, 'json:', args[jsonArg])
38+
exit(1)
39+
40+
try:
41+
# Create a MessageBird client with the specified accessKey.
42+
client = messagebird.Client(args['accessKey'])
43+
del(args['accessKey'])
44+
45+
# Create a call for the specified callID.
46+
call = client.call_create(**args)
47+
48+
# Print the object information.
49+
print('\nThe following information was returned as a', str(call.__class__), 'object:\n')
50+
51+
except messagebird.client.ErrorException as e:
52+
print('\nAn error occurred while creating a call:\n')
53+
54+
for error in e.errors:
55+
print(' code : %d' % error.code)
56+
print(' description : %s' % error.description)
57+
print(' parameter : %s' % error.parameter)
58+
print(' type : %s' % error.__class__)
59+
60+
except requests.exceptions.HTTPError as e:
61+
print('\nAn http exception occurred while creating a call:')
62+
print(' ', e)
63+
print(' Http request body: ', e.request.body)
64+
print(' Http response status: ', e.response.status_code)
65+
print(' Http response body: ', e.response.content.decode())
66+
67+
except Exception as e:
68+
print('\nAn ', e.__class__, ' exception occurred while creating a call:')
69+
print(e)
70+

messagebird/call.py

+6
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,9 @@ def data(self):
1919
@data.setter
2020
def data(self, value):
2121
self._data = CallData().load(value[0])
22+
23+
def __str__(self):
24+
return "\n".join([
25+
'id : %s' % self.id,
26+
'data.'+'data.'.join(str(self._data).splitlines(True)),
27+
])

messagebird/call_data.py

+9
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,12 @@ def webhook(self):
4545
@webhook.setter
4646
def webhook(self, value):
4747
self._webhook = Webhook.load(value)
48+
49+
def __str__(self):
50+
return "\n".join([
51+
'id : %s' % self.id,
52+
'updatedAt : %s' % self.updatedAt,
53+
'createdAt : %s' % self.createdAt,
54+
'endedAt : %s' % self.endedAt,
55+
'webhook : %s' % self.webhook,
56+
])

messagebird/client.py

+23-4
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,25 @@ def call(self,id):
124124
"""Retrieve the information of a specific call"""
125125
return Call().load(self.request('calls/' + str(id), 'GET', None, VOICE_TYPE))
126126

127+
def call_create(self, source, destination, callFlow, webhook):
128+
"""Creating a call
129+
130+
Args:
131+
source(str) : The caller ID of the call.
132+
destination(string) : The number/address to be called.
133+
callFlow(object) : The call flow object to be executed when the call is answered.
134+
webhook(object) : The webhook object containing the url & required token.
135+
Raises:
136+
ErrorException: On api returning errors
137+
138+
Returns:
139+
If successful, this request will return an object with a data property, which is an array that has a single
140+
call object. If the request failed, an error object will be returned."""
141+
142+
params = locals()
143+
del(params['self'])
144+
return Call().load(self.request('calls', 'POST', params, VOICE_TYPE))
145+
127146
def hlr(self, id):
128147
"""Retrieve the information of a specific HLR lookup."""
129148
return HLR().load(self.request('hlr/' + str(id)))
@@ -155,11 +174,11 @@ def message_delete(self, id):
155174
self.request_plain_text('messages/' + str(id), 'DELETE')
156175

157176
def mms_create(self, originator, recipients, body, mediaUrls, subject = None, reference = None, scheduledDatetime = None):
158-
''' Send bulk mms.
177+
""" Send bulk mms.
159178
160179
Args:
161180
originator(str): name of the originator
162-
recipients(str/list(str)): comma seperated numbers or list of numbers in E164 format
181+
recipients(str/list(str)): comma separated numbers or list of numbers in E164 format
163182
body(str) : text message body
164183
mediaUrl(str) : list of URL's of attachments of the MMS message.
165184
subject(str) : utf-encoded subject
@@ -169,8 +188,8 @@ def mms_create(self, originator, recipients, body, mediaUrls, subject = None, re
169188
ErrorException: On api returning errors
170189
171190
Returns:
172-
MMS: On success an MMS instance instantiated with succcess response
173-
'''
191+
MMS: On success an MMS instance instantiated with success response
192+
"""
174193
if isinstance(recipients,list):
175194
recipients = ','.join(recipients)
176195
if isinstance(mediaUrls,str):

tests/test_call.py

+105-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import json
12
import unittest
23
from messagebird import Client, ErrorException
4+
from messagebird.base import Base
35

46
try:
57
from unittest.mock import Mock
@@ -13,10 +15,111 @@ class TestCall(unittest.TestCase):
1315

1416
def test_call(self):
1517
http_client = Mock()
16-
http_client.request.return_value = '{"data":[{"id":"call-id","status":"ended","source":"16479311111","destination":"1416555555","createdAt":"2019-08-06T13:17:06Z","updatedAt":"2019-08-06T13:17:39Z","endedAt":"2019-08-06T13:17:39Z"}],"_links":{"legs":"/calls/66bd9f08-a8af-40fe-a830-652d8dabc057/legs","self":"/calls/66bd9f08-a8af-40fe-a830-652d8bca357"},"pagination":{"totalCount":0,"pageCount":0,"currentPage":0,"perPage":0}}'
18+
http_client.request.return_value = """
19+
{
20+
"data":[
21+
{
22+
"id":"call-id",
23+
"status":"ended",
24+
"source":"16479311111",
25+
"destination":"1416555555",
26+
"createdAt":"2019-08-06T13:17:06Z",
27+
"updatedAt":"2019-08-06T13:17:39Z",
28+
"endedAt":"2019-08-06T13:17:39Z"
29+
}
30+
],
31+
"_links":{
32+
"legs":"/calls/66bd9f08-a8af-40fe-a830-652d8dabc057/legs",
33+
"self":"/calls/66bd9f08-a8af-40fe-a830-652d8bca357"
34+
},
35+
"pagination":{
36+
"totalCount":0,
37+
"pageCount":0,
38+
"currentPage":0,
39+
"perPage":0
40+
}
41+
}
42+
"""
1743

1844
call = Client('', http_client).call('call-id')
1945

2046
http_client.request.assert_called_once_with('calls/call-id', 'GET', None)
2147

22-
self.assertEqual('ended', call.data.status)
48+
self.assertEqual('ended', call.data.status)
49+
50+
def test_call_create(self):
51+
api_response = {
52+
"data": [
53+
{
54+
"id": "21025ed1-cc1d-4554-ac05-043fa6c84e00",
55+
"status": "queued",
56+
"source": "31644556677",
57+
"destination": "31612345678",
58+
"createdAt": "2017-08-30T07:35:37Z",
59+
"updatedAt": "2017-08-30T07:35:37Z",
60+
"endedAt": None
61+
}
62+
],
63+
"_links": {
64+
"self": "/calls/21025ed1-cc1d-4554-ac05-043fa6c84e00"
65+
}
66+
}
67+
68+
params = {
69+
"source": "31644556677",
70+
"destination": "31612345678",
71+
"callFlow": {
72+
"title": "Say message",
73+
"steps": [
74+
{
75+
"action": "say",
76+
"options": {
77+
"payload": "This is a journey into sound. Good bye!",
78+
"voice": "male",
79+
"language": "en-US"
80+
}
81+
}
82+
]
83+
},
84+
"webhook": {
85+
"url": "https://example.com",
86+
"token": "token_to_sign_the_call_events_with",
87+
}
88+
}
89+
90+
http_client = Mock()
91+
http_client.request.return_value = json.dumps(api_response)
92+
93+
call_creation_response = Client('', http_client).call_create(**params)
94+
95+
http_client.request.assert_called_once_with('calls', 'POST', params)
96+
97+
# check all api response data is outputted
98+
expected_data = self.create_expected_call_data_based_on_api_response(api_response)
99+
response_data = call_creation_response.data.__dict__
100+
self.assertEqual(expected_data, response_data, 'Check client response contains the api response data.')
101+
102+
# check it can be formatted as string
103+
expected_call_string = 'id : None\n' + \
104+
'data.id : 21025ed1-cc1d-4554-ac05-043fa6c84e00\n' + \
105+
'data.updatedAt : 2017-08-30 07:35:37+00:00\n' + \
106+
'data.createdAt : 2017-08-30 07:35:37+00:00\n' + \
107+
'data.endedAt : None\n' + \
108+
'data.webhook : None'
109+
self.assertEqual(expected_call_string, str(call_creation_response), 'Check returned call can be formatted as' +
110+
'string')
111+
112+
@staticmethod
113+
def create_expected_call_data_based_on_api_response(api_response):
114+
expected_data = api_response['data'][0]
115+
116+
# convert dates
117+
expected_data['_createdAt'] = Base.value_to_time(expected_data['createdAt'], '%Y-%m-%dT%H:%M:%SZ')
118+
expected_data['_updatedAt'] = Base.value_to_time(expected_data['updatedAt'], '%Y-%m-%dT%H:%M:%SZ')
119+
expected_data['_endedAt'] = Base.value_to_time(expected_data['endedAt'], '%Y-%m-%dT%H:%M:%SZ')
120+
del (expected_data['createdAt'], expected_data['updatedAt'], expected_data['endedAt'])
121+
122+
# add generated data
123+
expected_data.setdefault('_webhook', None)
124+
125+
return expected_data

0 commit comments

Comments
 (0)