Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions bandwidth/model/bxml/terminal_verb.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ class TerminalVerb(Verb):
"""Base class for BXML verbs
"""

def __init__(self, tag: str, content: str = None, attributes: dict = None):
def __init__(self, tag: str, content: str = None):
"""Initialize the verb model

Args:
tag (str): Name of the XML element
content (str, optional): XML element content. Defaults to None.
attributes (dict, optional): XML element attributes. Defaults to None.
"""
super().__init__(tag=tag, content=content, attributes=attributes, nested_verbs=None)
super().__init__(tag=tag, content=content, nested_verbs=None)

def add_verb(self, verb: Verb):
"""Adding verbs is not allowed for this class
Expand Down
11 changes: 7 additions & 4 deletions bandwidth/model/bxml/verb.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,32 @@
@copyright Bandwidth INC
"""
from __future__ import annotations
from typing import Union
import xml.etree.ElementTree as ET


class Verb:
"""Base class for BXML verbs
"""

def __init__(self, tag: str, content: str = None, attributes: dict = None, nested_verbs: list[Verb] = None):
def __init__(self, tag: str, content: str = None, nested_verbs: list[Verb] = None):
"""Initialize the verb model

Args:
tag (str): Name of the XML element
content (str, optional): XML element content. Defaults to None.
attributes (dict, optional): XML element attributes. Defaults to None.
nested_verbs (list[BxmlVerb], optional): XML element children. Defaults to None.
"""
self._tag = tag
self._content = content
self._attributes = attributes
self._nested_verbs = nested_verbs
if not self._nested_verbs:
self._nested_verbs = []

@property
def _attributes(self) -> Union[None, dict]:
return None

def __len__(self) -> int:
"""Override default len method. Returns length of _nested_verbs array

Expand All @@ -54,7 +57,7 @@ def _set_attributes(self, root: ET.Element):
Args:
root (ET.Element): XML Element to add attributes to
"""
if self._attributes:
if self._attributes is not None:
for key, value in self._attributes.items():
if value is not None:
root.set(key, value)
Expand Down
1 change: 1 addition & 0 deletions bandwidth/model/bxml/verbs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .bridge import Bridge
from .phone_number import PhoneNumber
from .record import Record
from .sip_uri import SipUri
from .tag import Tag
from .transfer import Transfer
14 changes: 8 additions & 6 deletions bandwidth/model/bxml/verbs/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,14 @@ def __init__(
self.fallback_username = fallback_username
self.fallback_password = fallback_password
self.tag = tag
self.attributes = {
super().__init__(
tag="Bridge",
content=self.target_call,
)

@property
def _attributes(self):
return {
"bridgeCompleteUrl": self.bridge_complete_url,
"bridgeCompleteMethod": self.bridge_complete_method,
"bridgeCompleteFallbackUrl": self.bridge_complete_fallback_url,
Expand All @@ -70,8 +77,3 @@ def __init__(
"fallbackPassword": self.fallback_password,
"tag": self.tag
}
super().__init__(
tag="Bridge",
content=self.target_call,
attributes=self.attributes
)
14 changes: 8 additions & 6 deletions bandwidth/model/bxml/verbs/phone_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@ def __init__(
self.fallback_username = fallback_username
self.fallback_password = fallback_password
self.tag = tag
self.attributes = {
super().__init__(
tag="PhoneNumber",
content=self.number
)

@property
def _attributes(self):
return {
"transferAnswerUrl": self.transfer_answer_url,
"transferAnswerMethod": self.transfer_answer_method,
"transferAnswerFallbackUrl": self.transfer_answer_fallback_url,
Expand All @@ -57,8 +64,3 @@ def __init__(
"fallbackPassword": self.fallback_password,
"tag": self.tag
}
super().__init__(
tag="PhoneNumber",
content=self.number,
attributes=self.attributes
)
90 changes: 90 additions & 0 deletions bandwidth/model/bxml/verbs/record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
record.py

Bandwidth's Record BXML verb

@copyright Bandwidth INC
"""
from ..terminal_verb import TerminalVerb


class Record(TerminalVerb):

def __init__(
self, record_complete_url: str = None,
record_complete_method: str = None,
record_complete_fallback_url: str = None,
record_complete_fallback_method: str = None,
recording_available_url: str = None,
recording_available_method: str = None,
transcribe: str = None, transcription_available_url: str = None,
transcription_available_method: str = None, username: str=None,
password: str=None, fallback_username: str=None,
fallback_password: str=None, tag: str=None,
terminating_digits: str = None, max_duration: str = None,
silence_timeout: str = None, file_format: str = None
):
"""Initialize a <Record> verb

Args:
record_complete_url (str, optional): URL to send the Record Complete event to once the recording has ended. Accepts BXML, and may be a relative URL. This callback will not be sent if the recording ended due to the call hanging up. Defaults to None.
record_complete_method (str, optional): The HTTP method to use for the request to recordCompleteUrl. GET or POST. Default value is POST. Defaults to None.
record_complete_fallback_url (str, optional): A fallback url which, if provided, will be used to retry the Record Complete callback delivery in case recordCompleteUrl fails to respond. Defaults to None.
record_complete_fallback_method (str, optional): The HTTP method to use to deliver the Record Complete callback to recordCompleteFallbackUrl. GET or POST. Default value is POST. Defaults to None.
recording_available_url (str, optional): URL to send the Recording Available event to once it has been processed. Does not accept BXML. May be a relative URL. Defaults to None.
recording_available_method (str, optional): The HTTP method to use for the request to recordingAvailableUrl. GET or POST. Default value is POST. Defaults to None.
transcribe (str, optional): A boolean value to indicate that recording should be transcribed. Transcription can succeed only for recordings of length greater than 500 milliseconds and less than 4 hours. Default is false. Defaults to None.
transcription_available_url (str, optional): URL to send the Transcription Available event to once it has been processed. Does not accept BXML. May be a relative URL. Defaults to None.
transcription_available_method (str, optional): The HTTP method to use for the request to transcriptionAvailableUrl. GET or POST. Default value is POST. Defaults to None.
username (str, optional): The username to send in the HTTP request to recordCompleteUrl, recordingAvailableUrl or transcriptionAvailableUrl. If specified, the URLs must be TLS-encrypted (i.e., https). Defaults to None.
password (str, optional): The password to send in the HTTP request to recordCompleteUrl, recordingAvailableUrl or transcriptionAvailableUrl. If specified, the URLs must be TLS-encrypted (i.e., https). Defaults to None.
fallback_username (str, optional): The username to send in the HTTP request to recordCompleteFallbackUrl. If specified, the URLs must be TLS-encrypted (i.e., https). Defaults to None.
fallback_password (str, optional): The password to send in the HTTP request to recordCompleteFallbackUrl. If specified, the URLs must be TLS-encrypted (i.e., https). Defaults to None.
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="". Max length 256 characters. Defaults to None.
terminating_digits (str, optional): When pressed, this digit will terminate the recording. Default value is “#”. This feature can be disabled with "". Defaults to None.
max_duration (str, optional): Maximum length of recording (in seconds). Max 10800 (3 hours). Default value is 60. Defaults to None.
silence_timeout (str, optional): Length of silence after which to end the recording (in seconds). Max is equivalent to the maximum maxDuration value. Default value is 0, which means no timeout. Defaults to None.
file_format (str, optional): The audio format that the recording will be saved as: mp3 or wav. Default value is wav. Defaults to None.
"""
self.record_complete_url = record_complete_url
self.record_complete_method = record_complete_method
self.record_complete_fallback_url = record_complete_fallback_url
self.record_complete_fallback_method = record_complete_fallback_method
self.recording_available_url = recording_available_url
self.recording_available_method = recording_available_method
self.transcribe = transcribe
self.transcription_available_url = transcription_available_url
self.transcription_available_method = transcription_available_method
self.username = username
self.password = password
self.fallback_username = fallback_username
self.fallback_password = fallback_password
self.tag = tag
self.terminating_digits = terminating_digits
self.max_duration = max_duration
self.silence_timeout = silence_timeout
self.file_format = file_format
super().__init__(tag="Record", content=None)

@property
def _attributes(self):
return {
"recordCompleteUrl": self.record_complete_url,
"recordCompleteMethod": self.record_complete_method,
"recordCompleteFallback_url": self.record_complete_fallback_url,
"recordCompleteFallback_method": self.record_complete_fallback_method,
"recordingAvailableUrl": self.recording_available_url,
"recordingAvailableMethod": self.recording_available_method,
"transcribe": self.transcribe,
"transcriptionAvailableUrl": self.transcription_available_url,
"transcriptionAvailableMethod": self.transcription_available_method,
"username": self.username,
"password": self.password,
"fallbackUsername": self.fallback_username,
"fallbackPassword": self.fallback_password,
"tag": self.tag,
"terminatingDigits": self.terminating_digits,
"maxDuration": self.max_duration,
"silenceTimeout": self.silence_timeout,
"fileFormat": self.file_format
}
16 changes: 9 additions & 7 deletions bandwidth/model/bxml/verbs/sip_uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,15 @@ def __init__(
self.fallback_username = fallback_username
self.fallback_password = fallback_password
self.tag = tag
self.attributes = {
"uui": uui,
super().__init__(
tag="SipUri",
content=self.uri,
)

@property
def _attributes(self):
return {
"uui": self.uui,
"transferAnswerUrl": self.transfer_answer_url,
"transferAnswerMethod": self.transfer_answer_method,
"transferAnswerFallbackUrl": self.transfer_answer_fallback_url,
Expand All @@ -60,8 +67,3 @@ def __init__(
"fallbackPassword": self.fallback_password,
"tag": self.tag
}
super().__init__(
tag="SipUri",
content=self.uri,
attributes=self.attributes
)
2 changes: 1 addition & 1 deletion bandwidth/model/bxml/verbs/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ def __init__(self, content=""):
content (str, optional): Custom tag value. Defaults to "".
"""
self.content = content
super().__init__(tag="Tag", content=self.content, attributes=None)
super().__init__(tag="Tag", content=self.content)
16 changes: 9 additions & 7 deletions bandwidth/model/bxml/verbs/transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,15 @@ def __init__(
self.tag = tag
self.diversion_treatment = diversion_treatment
self.diversion_reason = diversion_reason
self.attributes = {
super().__init__(
tag="Transfer",
content=None,
nested_verbs=self.transfer_to
)

@property
def _attributes(self):
return {
"transferCallerId": self.transfer_caller_id,
"callTimeout": self.call_timeout,
"transferCompleteUrl": self.transfer_complete_url,
Expand All @@ -90,12 +98,6 @@ def __init__(
"diversionTreatment": self.diversion_treatment,
"diversionReason": self.diversion_reason
}
super().__init__(
tag="Transfer",
content=None,
attributes=self.attributes,
nested_verbs=self.transfer_to
)

def add_transfer_recipient(self, recipient: Union[PhoneNumber, SipUri]):
super().add_verb(recipient)
30 changes: 30 additions & 0 deletions test/unit/bxml/test_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
test_record.py

Unit tests for the <Record> BXML verb

@copyright Bandwidth Inc.
"""
import pytest
import unittest

from bandwidth.model.bxml.verb import Verb
from bandwidth.model.bxml.verbs.record import Record


class TestRecord(unittest.TestCase):

def setUp(self):
self.record = Record()
self.record.max_duration = "10"
self.test_verb = Verb(tag="test")

def test_to_bxml(self):
expected = '<Record maxDuration="10" />'
assert(expected == self.record.to_bxml())


def test_add_verb(self):
with pytest.raises(AttributeError):
self.record.add_verb(self.test_verb)