Skip to content

Commit 087ae7f

Browse files
DX2897, DX2902, DX2909
1 parent 4eeea97 commit 087ae7f

File tree

7 files changed

+285
-0
lines changed

7 files changed

+285
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from .bridge import Bridge
2+
from .gather import Gather
23
from .phone_number import PhoneNumber
4+
from .play_audio import PlayAudio
35
from .sip_uri import SipUri
6+
from .speak_sentence import SpeakSentence
47
from .tag import Tag
58
from .transfer import Transfer
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
gather.py
3+
4+
Bandwidth's Gather BXML verb
5+
6+
@copyright Bandwidth INC
7+
"""
8+
from typing import Union, List
9+
from ..verb import Verb
10+
from .play_audio import PlayAudio
11+
from .speak_sentence import SpeakSentence
12+
13+
14+
class Gather(Verb):
15+
16+
def __init__(
17+
self, audio_verbs: List[Union[PlayAudio, SpeakSentence]] = [],
18+
gather_url: str=None, gather_method: str=None,
19+
gather_fallback_url: str=None, gather_fallback_method: str=None,
20+
username: str=None, password: str=None,
21+
fallback_username: str=None, fallback_password: str=None,
22+
tag: str=None, terminating_digits: str=None,
23+
max_digits: str=None, inter_digit_timeout: str=None,
24+
first_digit_timeout: str=None, repeat_count: str=None
25+
):
26+
"""Initialize a <Gather> verb
27+
28+
Args:
29+
gather_url (str, optional): URL to send Gather event to and request new BXML. May be a relative URL.
30+
gather_method (str, optional): The HTTP method to use for the request to gather_url. GET or POST. Default value is POST.
31+
gather_fallback_url (str, optional): A fallback url which, if provided, will be used to retry the Gather event callback delivery in case gather_url fails to respond.
32+
gather_fallback_method (str, optional): The HTTP method to use to deliver the Gather event callback to gather_fallback_url. GET or POST. Default value is POST.
33+
username (str, optional): The username to send in the HTTP request to gather_url.
34+
password (str, optional): The password to send in the HTTP request to gather_url.
35+
fallback_username (str, optional): The username to send in the HTTP request to gather_fallback_url.
36+
fallback_password (str, optional): The password to send in the HTTP request to gather_fallback_url.
37+
tag (str, optional): A custom string that will be sent with this and all future callbacks unless overwritten by a future tag attribute or <Tag> verb, or cleared.
38+
May be cleared by setting tag="". Max length 256 characters.
39+
terminating_digits (str, optional): When any of these digits are pressed, it will terminate the Gather. Default value is "", which disables this feature.
40+
max_digits (str, optional): Max number of digits to collect. Default value is 50. Range: decimal values between 1 - 50.
41+
inter_digit_timeout (str, optional): Time (in seconds) allowed between digit presses before automatically terminating the Gather. Default value is 5. Range: decimal values between 1 - 60.
42+
first_digit_timeout (str, optional): Time (in seconds) to pause after any audio from nested <SpeakSentence> or <PlayAudio> verb is played (in seconds) before terminating the Gather.
43+
Default value is 5. Range: decimal values between 0 - 60.
44+
repeat_count (str, optional): The number of times the audio prompt should be played if no digits are pressed. For example, if this value is 3, the nested audio clip will be played a maximum of three times.
45+
The delay between repetitions will be equal to first_digit_timeout. Default value is 1. repeat_count * number of verbs must not be greater than 20.
46+
47+
Nested Verbs:
48+
PlayAudio: (optional) Using the PlayAudio inside the Gather verb will play the media until a digit is received.
49+
SpeakSentence: (optional) Using the SpeakSentence inside the Gather verb will speak the text until a digit is received.
50+
"""
51+
self.gather_url = gather_url
52+
self.gather_method = gather_method
53+
self.gather_fallback_url = gather_fallback_url
54+
self.gather_fallback_method = gather_fallback_method
55+
self.username = username
56+
self.password = password
57+
self.fallback_username = fallback_username
58+
self.fallback_password = fallback_password
59+
self.tag = tag
60+
self.terminating_digits = terminating_digits
61+
self.max_digits = max_digits
62+
self.inter_digit_timeout = inter_digit_timeout
63+
self.first_digit_timeout = first_digit_timeout
64+
self.repeat_count = repeat_count
65+
self.audio_verbs = audio_verbs
66+
self.attributes = {
67+
"gather_url": gather_url,
68+
"gather_method": gather_method,
69+
"gather_fallback_url": gather_fallback_url,
70+
"gather_fallback_method": gather_fallback_method,
71+
"username": username,
72+
"password": password,
73+
"fallback_username": fallback_username,
74+
"fallback_password": fallback_password,
75+
"tag": tag,
76+
"terminating_digits": terminating_digits,
77+
"max_digits": max_digits,
78+
"inter_digit_timeout": inter_digit_timeout,
79+
"first_digit_timeout": first_digit_timeout,
80+
"repeat_count": repeat_count,
81+
}
82+
83+
super().__init__(tag="Gather", content=None, attributes=self.attributes, nested_verbs=self.audio_verbs)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
play_audio.py
3+
4+
Bandwidth's PlayAudio BXML verb
5+
6+
@copyright Bandwidth INC
7+
"""
8+
from ..terminal_verb import TerminalVerb
9+
10+
11+
class PlayAudio(TerminalVerb):
12+
13+
def __init__(
14+
self, audio_uri: str,
15+
username: str=None, password: str=None
16+
):
17+
"""Initialize a <PlayAudio> verb
18+
19+
Args:
20+
audio_uri (str): The URL of the audio file to play. May be a relative URL.
21+
username (str, optional): The username to send in the HTTP request to audio_uri.
22+
password (str, optional): The password to send in the HTTP request to audio_uri.
23+
"""
24+
self.audio_uri = audio_uri
25+
self.username = username
26+
self.password = password
27+
self.attributes = {
28+
"username": self.username,
29+
"password": self.password,
30+
}
31+
super().__init__(
32+
tag="PlayAudio",
33+
content=self.audio_uri,
34+
attributes=self.attributes
35+
)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
speak_sentence.py
3+
4+
Bandwidth's SpeakSentence BXML verb
5+
6+
@copyright Bandwidth INC
7+
"""
8+
from ..terminal_verb import TerminalVerb
9+
10+
11+
class SpeakSentence(TerminalVerb):
12+
13+
def __init__(
14+
self, text: str, voice: str=None,
15+
gender: str=None, locale: str=None
16+
):
17+
"""Initialize a <SpeakSentence> verb
18+
19+
Args:
20+
text (str): The text to speak. Cannot be blank. Can be a mixture of plain text and SSML tags.
21+
You can find a list of supported SSML tags here: https://dev.bandwidth.com/docs/voice/bxml/speakSentence/#supported-ssml-tags
22+
voice (str, optional): Selects the voice of the speaker. Consult the voice column in the below table for valid values.
23+
If the voice attribute is present, gender and locale are ignored. You can find a list of supported voices here: https://dev.bandwidth.com/docs/voice/bxml/speakSentence/#supported-voices
24+
gender (str, optional): Selects the gender of the speaker. Valid values are "male" or "female". Default "female".
25+
locale (str, optional): Selects the locale of the speaker. Consult the locale column in the below table for valid values. Default "en_US"
26+
"""
27+
self.text = text
28+
self.voice = voice
29+
self.gender = gender
30+
self.locale = locale
31+
self.attributes = {
32+
"voice": self.voice,
33+
"gender": self.gender,
34+
"locale": self.locale,
35+
}
36+
super().__init__(
37+
tag="SpeakSentence",
38+
content=self.text,
39+
attributes=self.attributes
40+
)

test/unit/bxml/test_gather.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
test_gather.py
3+
4+
Unit tests for the <Gather> BXML verb
5+
6+
@copyright Bandwidth Inc.
7+
"""
8+
import os
9+
import pytest
10+
import unittest
11+
12+
from bandwidth.model.bxml.verb import Verb
13+
from bandwidth.model.bxml.verbs import PlayAudio,SpeakSentence,Gather
14+
15+
class TestGather(unittest.TestCase):
16+
17+
def setUp(self):
18+
self.play_audio = PlayAudio(
19+
audio_uri="https://audio.url/audio1.wav",
20+
username="user",
21+
password="pass"
22+
)
23+
24+
self.speak_sentence = SpeakSentence(
25+
text='Hello. Your number is <say-as interpret-as="telephone">asdf</say-as>, lets play a game. What is 10 + 3. Press the pound key when finished.'
26+
)
27+
28+
self.gather = Gather(
29+
gather_url="test.com",
30+
gather_method="POST",
31+
gather_fallback_url= "fallback-test.com",
32+
gather_fallback_method="GET",
33+
username="user",
34+
password="pass",
35+
fallback_username="user",
36+
fallback_password="pass",
37+
tag = "tag",
38+
terminating_digits = "2",
39+
max_digits = "5",
40+
inter_digit_timeout = "1",
41+
first_digit_timeout = "3",
42+
repeat_count = "2",
43+
audio_verbs=[self.play_audio]
44+
)
45+
46+
def test_to_bxml(self):
47+
if os.environ['PYTHON_VERSION'] == '3.7':
48+
expected = '<Gather fallback_password="pass" fallback_username="user" first_digit_timeout="3" gather_url="test.com" gather_method="POST" gather_fallback_url="fallback-test.com" gather_fallback_method="GET" inter_digit_timeout="1" password="pass" max_digits="5"><PlayAudio password="pass" username="user">https://audio.url/audio1.wav</PlayAudio> repeat_count="2" tag="tag" terminating_digits="2" username="user"</Gather>'
49+
else:
50+
expected = '<Gather gather_url="test.com" gather_method="POST" gather_fallback_url="fallback-test.com" gather_fallback_method="GET" username="user" password="pass" fallback_username="user" fallback_password="pass" tag="tag" terminating_digits="2" max_digits="5" inter_digit_timeout="1" first_digit_timeout="3" repeat_count="2"><PlayAudio username="user" password="pass">https://audio.url/audio1.wav</PlayAudio></Gather>'
51+
assert(expected == self.gather.to_bxml())
52+
53+
def test_add_verb(self):
54+
if os.environ['PYTHON_VERSION'] == '3.7':
55+
expected = '<Gather fallback_password="pass" fallback_username="user" first_digit_timeout="3" gather_url="test.com" gather_method="POST" gather_fallback_url="fallback-test.com" gather_fallback_method="GET" inter_digit_timeout="1" password="pass" max_digits="5"><PlayAudio password="pass" username="user">https://audio.url/audio1.wav</PlayAudio> repeat_count="2" <SpeakSentence>Hello. Your number is &lt;say-as interpret-as="telephone"&gt;asdf&lt;/say-as&gt;, lets play a game. What is 10 + 3. Press the pound key when finished.</SpeakSentence> tag="tag" terminating_digits="2" username="user"</Gather>'
56+
else:
57+
expected = '<Gather gather_url="test.com" gather_method="POST" gather_fallback_url="fallback-test.com" gather_fallback_method="GET" username="user" password="pass" fallback_username="user" fallback_password="pass" tag="tag" terminating_digits="2" max_digits="5" inter_digit_timeout="1" first_digit_timeout="3" repeat_count="2"><PlayAudio username="user" password="pass">https://audio.url/audio1.wav</PlayAudio><SpeakSentence>Hello. Your number is &lt;say-as interpret-as="telephone"&gt;asdf&lt;/say-as&gt;, lets play a game. What is 10 + 3. Press the pound key when finished.</SpeakSentence></Gather>'
58+
self.gather.add_verb(self.speak_sentence)
59+
assert(expected == self.gather.to_bxml())

test/unit/bxml/test_play_audio.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
test_play_audio.py
3+
4+
Unit tests for the <PlayAudio> BXML verb
5+
6+
@copyright Bandwidth Inc.
7+
"""
8+
import os
9+
import pytest
10+
import unittest
11+
12+
from bandwidth.model.bxml.verb import Verb
13+
from bandwidth.model.bxml.verbs import PlayAudio
14+
15+
class TestPlayAudio(unittest.TestCase):
16+
17+
def setUp(self):
18+
self.play_audio = PlayAudio(
19+
audio_uri="https://audio.url/audio1.wav",
20+
username="user",
21+
password="pass"
22+
)
23+
self.test_verb = Verb(tag="test")
24+
25+
26+
def test_to_bxml(self):
27+
if os.environ['PYTHON_VERSION'] == '3.7':
28+
expected = '<PlayAudio password="pass" username="user">https://audio.url/audio1.wav</PlayAudio>'
29+
else:
30+
expected = '<PlayAudio username="user" password="pass">https://audio.url/audio1.wav</PlayAudio>'
31+
assert(expected == self.play_audio.to_bxml())
32+
33+
def test_add_verb(self):
34+
with pytest.raises(AttributeError):
35+
self.play_audio.add_verb(self.test_verb)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
test_speak_sentence.py
3+
4+
Unit tests for the <SpeakSentence> BXML verb
5+
6+
@copyright Bandwidth Inc.
7+
"""
8+
import os
9+
import pytest
10+
import unittest
11+
12+
from bandwidth.model.bxml.verb import Verb
13+
from bandwidth.model.bxml.verbs import SpeakSentence
14+
15+
class TestSpeakSentence(unittest.TestCase):
16+
17+
def setUp(self):
18+
self.speak_sentence = SpeakSentence(
19+
text='Hello. Your number is <say-as interpret-as="telephone">asdf</say-as>, lets play a game. What is 10 + 3. Press the pound key when finished.'
20+
)
21+
22+
self.test_verb = Verb(tag="test")
23+
24+
def test_to_bxml(self):
25+
expected = '<SpeakSentence>Hello. Your number is &lt;say-as interpret-as="telephone"&gt;asdf&lt;/say-as&gt;, lets play a game. What is 10 + 3. Press the pound key when finished.</SpeakSentence>'
26+
assert(expected == self.speak_sentence.to_bxml())
27+
28+
def test_add_verb(self):
29+
with pytest.raises(AttributeError):
30+
self.speak_sentence.add_verb(self.test_verb)

0 commit comments

Comments
 (0)