Skip to content

Commit 4eff2ff

Browse files
Merge pull request #122 from Bandwidth/DX-2897
DX-2897, DX-2902, DX-2909 - `<PlayAudio>`, `<SpeakSentence>`, and `<Gather>` verbs refactored
2 parents 757bac2 + f435e34 commit 4eff2ff

36 files changed

+1297
-3
lines changed

bandwidth/model/bxml/terminal_verb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ def add_verb(self, verb: Verb):
2828
verb (Verb): BXML verb
2929
3030
Raises:
31-
AttributeError: This method is not allowed for <SipUri>
31+
AttributeError: This method is not allowed for this verb
3232
"""
3333
raise AttributeError('Adding verbs is not supported by this verb')
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
from .bridge import Bridge
2+
from .conference import Conference
3+
from .hangup import Hangup
4+
from .gather import Gather
5+
from .pause import Pause
26
from .pause_recording import PauseRecording
37
from .phone_number import PhoneNumber
8+
from .play_audio import PlayAudio
49
from .record import Record
10+
from .ring import Ring
511
from .send_dtmf import SendDtmf
612
from .sip_uri import SipUri
13+
from .speak_sentence import SpeakSentence
14+
from .start_gather import StartGather
15+
from .start_recording import StartRecording
16+
from .start_stream import StartStream
17+
from .stop_gather import StopGather
18+
from .stop_stream import StopStream
19+
from .stop_recording import StopRecording
20+
from .stream_param import StreamParam
721
from .tag import Tag
822
from .transfer import Transfer
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""
2+
conference.py
3+
4+
Bandwidth's Conference 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+
from .start_recording import StartRecording
13+
from .stop_recording import StopRecording
14+
from .pause_recording import PauseRecording
15+
from .resume_recording import ResumeRecording
16+
17+
18+
class Conference(Verb):
19+
20+
def __init__(
21+
self, name: str,
22+
audio_and_recording_verbs: List[Union[PlayAudio, SpeakSentence, StartRecording, StopRecording, PauseRecording, ResumeRecording]] = [], mute: str=None,
23+
hold: str=None, call_ids_to_coach: str=None,
24+
conference_event_url: str=None, conference_event_method: str=None,
25+
conference_event_fallback_url: str=None, conference_event_fallback_method: str=None,
26+
username: str=None, password: str=None,
27+
fallback_username: str=None, fallback_password: str=None,
28+
tag: str=None, callback_timeout: str=None,
29+
):
30+
"""Initialize a <Conference> verb
31+
32+
Args:
33+
name (str): The name of the conference. Can contain up to 100 characters of letters, numbers, and the symbols -, _, and .
34+
mute (str, optional): A boolean value to indicate whether the member should be on mute in the conference. When muted, a member can hear others speak, but others cannot hear them speak. Defaults to false.
35+
hold (str, optional): A boolean value to indicate whether the member should be on hold in the conference. When on hold, a member cannot hear others, and they cannot be heard. Defaults to false.
36+
call_ids_to_coach (str, optional): A comma-separated list of call ids to coach. When a call joins a conference with this attribute set, it will coach the listed calls.
37+
Those calls will be able to hear and be heard by the coach, but other calls in the conference will not hear the coach.
38+
conference_event_url (str, optional): URL to send Conference events to. The URL, method, username, and password are set by the BXML document that creates the conference,
39+
and all events related to that conference will be delivered to that same endpoint. If more calls join afterwards and also have this property (or any other webhook related properties like username and password),
40+
they will be ignored and the original webhook information will be used. This URL may be a relative endpoint.
41+
conference_event_method (str, optional): The HTTP method to use for the request to conferenceEventUrl. GET or POST. Default value is POST.
42+
conference_event_fallback_url (str, optional): A fallback url which, if provided, will be used to retry the conference webhook deliveries in case conferenceEventUrl fails to respond.
43+
conference_event_fallback_method (str, optional): The HTTP method to use to deliver the conference webhooks to conferenceEventFallbackUrl. GET or POST. Default value is POST.
44+
username (str, optional):The username to send in the HTTP request to conferenceEventUrl.
45+
password (str, optional): The password to send in the HTTP request to conferenceEventUrl.
46+
fallback_username (str, optional): The username to send in the HTTP request to conferenceEventFallbackUrl.
47+
fallback_password (str, optional): The password to send in the HTTP request to conferenceEventFallbackUrl.
48+
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. May be cleared by setting tag="".
49+
Max length 256 characters. Defaults to None.
50+
callback_timeout (str, optional): This is the timeout (in seconds) to use when delivering webhooks for the conference.
51+
If not set, it will inherit the webhook timeout from the call that creates the conference. Can be any numeric value (including decimals) between 1 and 25.
52+
53+
Nested Verbs:
54+
PlayAudio: (optional)
55+
SpeakSentence: (optional)
56+
StartRecording: (optional)
57+
StopRecording: (optional)
58+
PauseRecording: (optional)
59+
ResumeRecording: (optional)
60+
"""
61+
self.name = name
62+
self.mute = mute
63+
self.hold = hold
64+
self.call_ids_to_coach = call_ids_to_coach
65+
self.conference_event_url = conference_event_url
66+
self.conference_event_method = conference_event_method
67+
self.conference_event_fallback_url = conference_event_fallback_url
68+
self.conference_event_fallback_method = conference_event_fallback_method
69+
self.username = username
70+
self.password = password
71+
self.fallback_username = fallback_username
72+
self.fallback_password = fallback_password
73+
self.tag = tag
74+
self.callback_timeout = callback_timeout
75+
self.audio_and_recording_verbs = audio_and_recording_verbs
76+
super().__init__(
77+
tag="Conference",
78+
content=self.name,
79+
nested_verbs=self.audio_and_recording_verbs)
80+
81+
@property
82+
def _attributes(self):
83+
return {
84+
"mute": self.mute,
85+
"hold": self.hold,
86+
"callIdsToCoach": self.call_ids_to_coach,
87+
"conferenceEventUrl": self.conference_event_url,
88+
"conferenceEventMethod": self.conference_event_method,
89+
"conferenceEventFallbackUrl": self.conference_event_fallback_url,
90+
"conferenceEventFallbackMethod": self.conference_event_fallback_method,
91+
"username": self.username,
92+
"password": self.password,
93+
"fallbackUsername": self.fallback_username,
94+
"fallbackPassword": self.fallback_password,
95+
"tag": self.tag,
96+
"callbackTimeout": self.callback_timeout,
97+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
forward.py
3+
4+
Bandwidth's Forward BXML verb
5+
6+
@copyright Bandwidth INC
7+
"""
8+
from ..terminal_verb import TerminalVerb
9+
10+
11+
class Forward(TerminalVerb):
12+
13+
def __init__(
14+
self, to: str=None, _from: str=None,
15+
call_timeout: str=None, diversion_treatment: str=None,
16+
diversion_reason: str=None, uui: str=None
17+
):
18+
"""Initialize a <Forward> verb
19+
20+
Args:
21+
to (str): The phone number destination of the call.
22+
from_ (str, optional): The phone number that the recipient will receive the call from.
23+
call_timeout (str, optional): The number of seconds to wait before timing out the call.
24+
diversion_treatment (str, optional): Can be any of the following:
25+
none: No diversion headers are sent on the outbound leg of the transferred call.
26+
propagate: Copy the Diversion header from the inbound leg to the outbound leg. Ignored if there is no Diversion header present on the inbound leg.
27+
stack: After propagating any Diversion header from the inbound leg to the outbound leg, stack on top another Diversion header based on the Request-URI of the inbound call.
28+
29+
Defaults to none. If diversionTreatment is not specified, no diversion header will be included for the transfer even if one came with the inbound call. Defaults to None.
30+
diversion_reason (str, optional): Can be any of the following values:
31+
unknown
32+
user-busy
33+
no-answer
34+
unavailable
35+
unconditional
36+
time-of-day
37+
do-not-disturb
38+
deflection
39+
follow-me
40+
out-of-service
41+
away
42+
43+
This parameter is considered only when diversionTreatment is set to stack. Defaults is unknown.
44+
Defaults to None.
45+
uui (str, optional): The value of the User-To-User header to send within the outbound INVITE when forwarding to a SIP URI.
46+
Must include the encoding parameter as specified in RFC 7433. Only base64 and jwt encoding are currently allowed.
47+
This value, including the encoding specifier, may not exceed 256 characters.
48+
"""
49+
self.to = to
50+
self._from = _from
51+
self.call_timeout = call_timeout
52+
self.diversion_treatment = diversion_treatment
53+
self.diversion_reason = diversion_reason
54+
self.uui = uui
55+
56+
super().__init__(tag="Forward")
57+
58+
@property
59+
def _attributes(self):
60+
return {
61+
"to": self.to,
62+
"_from": self._from,
63+
"callTimeout": self.call_timeout,
64+
"diversionTreatment": self.diversion_treatment,
65+
"diversionReason": self.diversion_reason,
66+
"uui": self.uui,
67+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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+
super().__init__(
67+
tag="Gather",
68+
nested_verbs=self.audio_verbs)
69+
70+
@property
71+
def _attributes(self):
72+
return {
73+
"gatherUrl": self.gather_url,
74+
"gatherMethod": self.gather_method,
75+
"gatherFallbackUrl": self.gather_fallback_url,
76+
"gatherFallbackMethod": self.gather_fallback_method,
77+
"username": self.username,
78+
"password": self.password,
79+
"fallbackUsername": self.fallback_username,
80+
"fallbackPassword": self.fallback_password,
81+
"tag": self.tag,
82+
"terminatingDigits": self.terminating_digits,
83+
"maxDigits": self.max_digits,
84+
"interDigitTimeout": self.inter_digit_timeout,
85+
"firstDigitTimeout": self.first_digit_timeout,
86+
"repeatCount": self.repeat_count,
87+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
hangup.py
3+
4+
Bandwidth's Hangup BXML verb
5+
6+
@copyright Bandwidth INC
7+
"""
8+
from ..terminal_verb import TerminalVerb
9+
10+
11+
class Hangup(TerminalVerb):
12+
13+
def __init__(self):
14+
"""Initialize a <Hangup> verb
15+
16+
Args:
17+
None
18+
"""
19+
super().__init__(tag="Hangup")
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
pause.py
3+
4+
Bandwidth's Pause BXML verb
5+
6+
@copyright Bandwidth INC
7+
"""
8+
from ..terminal_verb import TerminalVerb
9+
class Pause(TerminalVerb):
10+
def __init__(self, duration:str=None):
11+
"""Initialize a <Pause> verb
12+
Args:
13+
duration (str, optional): The time in seconds to pause. Default value is 1.
14+
"""
15+
self.duration = duration
16+
17+
super().__init__(tag="Pause")
18+
19+
@property
20+
def _attributes(self):
21+
return {
22+
"duration": self.duration
23+
}

bandwidth/model/bxml/verbs/pause_recording.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ class PauseRecording(TerminalVerb):
1313
def __init__(self):
1414
"""Initialize a <PauseRecording> verb
1515
"""
16-
super().__init__(tag="PauseRecording", content=None, attributes=None)
16+
super().__init__(tag="PauseRecording")
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
super().__init__(
28+
tag="PlayAudio",
29+
content=self.audio_uri,
30+
)
31+
32+
@property
33+
def _attributes(self):
34+
return {
35+
"username": self.username,
36+
"password": self.password,
37+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
record.py
3+
4+
Bandwidth's ResumeRecording BXML verb
5+
6+
@copyright Bandwidth INC
7+
"""
8+
from ..terminal_verb import TerminalVerb
9+
10+
11+
class ResumeRecording(TerminalVerb):
12+
13+
def __init__(
14+
self
15+
):
16+
"""Initialize a <ResumeRecording> verb
17+
18+
Args: There are no args or text content for ResumeRecording
19+
"""
20+
21+
super().__init__(tag="ResumeRecording", content=None)

0 commit comments

Comments
 (0)