Skip to content

Commit e6e3291

Browse files
DX-2465 add modifyCallBxml function (#86)
* DX-2465 add modifyCallBxml function * Add Tests * Revert accidental change * Update bandwidth/voice/bxml/bxml.py Co-authored-by: Brian <bgome004@gmail.com> * Update bandwidth/voice/bxml/bxml.py Co-authored-by: Brian <bgome004@gmail.com> * Update bandwidth/voice/bxml/bxml.py Co-authored-by: Brian <bgome004@gmail.com> * Update Version Co-authored-by: Brian <bgome004@gmail.com>
1 parent 510fcdd commit e6e3291

File tree

6 files changed

+119
-2
lines changed

6 files changed

+119
-2
lines changed

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@
22
.DS_Store
33
.idea/
44
*.pyc
5-
.pytest_cache/
5+
.pytest_cache/
6+
7+
# Build files
8+
build/
9+
bandwidth_sdk.egg-info
10+
pyproject.toml

bandwidth/tests/test_bxml.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
@copyright Bandwidth Inc.
77
"""
88
from bandwidth.voice.bxml.response import Response
9+
from bandwidth.voice.bxml.bxml import Bxml
910
from bandwidth.voice.bxml.verbs import *
1011
from bandwidth.webrtc.utils import *
1112

@@ -377,6 +378,24 @@ def test_gather_speak_sentence_ssml(self):
377378
response.add_verb(gather)
378379
assert response.to_bxml() == expected_bxml
379380

381+
def test_empty_bxml_verb(self):
382+
expected_bxml = '<?xml version="1.0" encoding="UTF-8"?><Bxml></Bxml>'
383+
384+
bxml = Bxml()
385+
assert bxml.to_bxml() == expected_bxml
386+
387+
def test_bxml_speak_sentence_pause(self):
388+
expected_bxml = '<?xml version="1.0" encoding="UTF-8"?><Bxml><SpeakSentence voice="Julie">Wee Woo</SpeakSentence><Pause duration="10"/></Bxml>'
389+
bxml = Bxml()
390+
speak_sentence = SpeakSentence(
391+
voice="Julie",
392+
sentence="Wee Woo"
393+
)
394+
pause = Pause(10)
395+
bxml.add_verb(speak_sentence)
396+
bxml.add_verb(pause)
397+
assert bxml.to_bxml() == expected_bxml
398+
380399
def test_generate_transfer_bxml(self):
381400
expected = '<?xml version="1.0" encoding="UTF-8"?><Response><Transfer><SipUri uui="93d6f3c0be5845960b744fa28015d8ede84bd1a4;encoding=base64,asdf;encoding=jwt">sip:sipx.webrtc.bandwidth.com:5060</SipUri></Transfer></Response>'
382401
actual = generate_transfer_bxml(
@@ -388,3 +407,5 @@ def test_generate_transfer_bxml_verb(self):
388407
actual = generate_transfer_bxml_verb(
389408
'asdf', 'c-93d6f3c0-be584596-0b74-4fa2-8015-d8ede84bd1a4')
390409
assert actual == expected
410+
411+

bandwidth/voice/bxml/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from . import response
2+
from . import bxml
23
from . import verbs

bandwidth/voice/bxml/bxml.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""
2+
bxml.py
3+
4+
Class that allows user to generate BXML programatically in python
5+
BXML is the parent element
6+
7+
@copyright Bandwidth INC
8+
"""
9+
10+
BXML_TAG = "Bxml"
11+
XML_HEADER = '<?xml version="1.0" encoding="UTF-8"?>'
12+
13+
14+
class Bxml:
15+
16+
def __init__(self):
17+
"""
18+
Creates the Bxml class
19+
"""
20+
self.verbs = []
21+
22+
def add_verb(self, verb):
23+
"""
24+
Adds the Verb to the already existing verbs
25+
26+
:param Verb verb: The Verb to add
27+
"""
28+
self.verbs.append(verb)
29+
30+
def to_bxml(self):
31+
"""
32+
Converts the Bxml class to its XML representation
33+
34+
:rtype str: The XML representation of the Bxml class
35+
"""
36+
xml_string = XML_HEADER
37+
xml_string += '<' + BXML_TAG + '>'
38+
for verb in self.verbs:
39+
xml_string += verb.to_bxml()
40+
xml_string += '</' + BXML_TAG + '>'
41+
42+
return xml_string

bandwidth/voice/controllers/api_controller.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,54 @@ def modify_call(self,
225225

226226
# Return appropriate type
227227
return ApiResponse(_response)
228+
229+
def modify_call_bxml(self, account_id, call_id, body):
230+
"""Does a PUT request to /api/v2/accounts/{accountId}/calls/{callId}/bxml.
231+
232+
Interrupts and replaces an active call's BXML document, sending the new BXML.
233+
234+
Args:
235+
account_id (string): Bandwidth Account ID. Ex: "99001234"
236+
call_id (string): ID of the call for which you wish to replace the active BXML instructions.
237+
body (string): XML string in valid BXML format
238+
"""
239+
240+
# Prepare query URL
241+
_url_path = '/api/v2/accounts/{accountId}/calls/{callId}/bxml'
242+
_url_path = APIHelper.append_url_with_template_parameters(_url_path, {
243+
'accountId': {'value': account_id, 'encode': False},
244+
'callId': {'value': call_id, 'encode': False}
245+
})
246+
_query_builder = self.config.get_base_uri(Server.VOICEDEFAULT)
247+
_query_builder += _url_path
248+
_query_url = APIHelper.clean_url(_query_builder)
249+
250+
# Prepare headers
251+
_headers = {
252+
'content-type': 'application/xml; charset=utf-8'
253+
}
254+
255+
# Prepare and execute request
256+
_request = self.config.http_client.put(_query_url, headers=_headers, parameters=body)
257+
VoiceBasicAuth.apply(self.config, _request)
258+
_response = self.execute_request(_request)
259+
260+
# Endpoint and global error handling using HTTP status codes.
261+
if _response.status_code == 400:
262+
raise ApiErrorException('Something\'s not quite right... Your request is invalid. Please fix it before trying again.', _response)
263+
elif _response.status_code == 401:
264+
raise APIException('Your credentials are invalid. Please use your Bandwidth dashboard credentials to authenticate to the API.', _response)
265+
elif _response.status_code == 403:
266+
raise ApiErrorException('User unauthorized to perform this action.', _response)
267+
elif _response.status_code == 404:
268+
raise ApiErrorException('The resource specified cannot be found or does not belong to you.', _response)
269+
elif _response.status_code == 415:
270+
raise ApiErrorException('We don\'t support that media type. If a request body is required, please send it to us as `application/json`.', _response)
271+
elif _response.status_code == 429:
272+
raise ApiErrorException('You\'re sending requests to this endpoint too frequently. Please slow your request rate down and try again.', _response)
273+
elif _response.status_code == 500:
274+
raise ApiErrorException('Something unexpected happened. Please try again.', _response)
275+
self.validate_response(_response)
228276

229277
def modify_call_recording_state(self,
230278
account_id,

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
setup(
1717
name='bandwidth-sdk',
18-
version='13.4.0',
18+
version='13.5.0',
1919
description='Bandwidth\'s set of APIs',
2020
long_description=long_description,
2121
long_description_content_type="text/markdown",

0 commit comments

Comments
 (0)