From 89889a5b86e4682b061422eb02513dba3d2cc43f Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 4 Oct 2022 15:46:00 -0400 Subject: [PATCH 1/4] DX-2895 --- bandwidth/model/bxml/verbs/__init__.py | 1 + bandwidth/model/bxml/verbs/conference.py | 97 ++++++++++++++++++++++++ test/unit/bxml/test_conference.py | 66 ++++++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 bandwidth/model/bxml/verbs/conference.py create mode 100644 test/unit/bxml/test_conference.py diff --git a/bandwidth/model/bxml/verbs/__init__.py b/bandwidth/model/bxml/verbs/__init__.py index 9ad5df88..d2f0d45d 100644 --- a/bandwidth/model/bxml/verbs/__init__.py +++ b/bandwidth/model/bxml/verbs/__init__.py @@ -1,4 +1,5 @@ from .bridge import Bridge +from .conference import Conference from .hangup import Hangup from .gather import Gather from .pause import Pause diff --git a/bandwidth/model/bxml/verbs/conference.py b/bandwidth/model/bxml/verbs/conference.py new file mode 100644 index 00000000..fb824f59 --- /dev/null +++ b/bandwidth/model/bxml/verbs/conference.py @@ -0,0 +1,97 @@ +""" +conference.py + +Bandwidth's Conference BXML verb + +@copyright Bandwidth INC +""" +from typing import Union, List +from ..verb import Verb +from .play_audio import PlayAudio +from .speak_sentence import SpeakSentence +from .start_recording import StartRecording +from .stop_recording import StopRecording +from .pause_recording import PauseRecording +from .resume_recording import ResumeRecording + + +class Conference(Verb): + + def __init__( + self, audio_and_recording_verbs: List[Union[PlayAudio, SpeakSentence, StartRecording, StopRecording, PauseRecording, ResumeRecording]] = [], + name: str=None, mute: str=None, + hold: str=None, call_ids_to_coach: str=None, + conference_event_url: str=None, conference_event_method: str=None, + conference_event_fallback_url: str=None, conference_event_fallback_method: str=None, + username: str=None, password: str=None, + fallback_username: str=None, fallback_password: str=None, + tag: str=None, callback_timeout: str=None, + ): + """Initialize a verb + + Args: + name (str): The name of the conference. Can contain up to 100 characters of letters, numbers, and the symbols -, _, and . + 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. + 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. + 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. + Those calls will be able to hear and be heard by the coach, but other calls in the conference will not hear the coach. + 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, + 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), + they will be ignored and the original webhook information will be used. This URL may be a relative endpoint. + conference_event_method (str, optional): The HTTP method to use for the request to conferenceEventUrl. GET or POST. Default value is POST. + 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. + 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. + username (str, optional):The username to send in the HTTP request to conferenceEventUrl. + password (str, optional): The password to send in the HTTP request to conferenceEventUrl. + fallback_username (str, optional): The username to send in the HTTP request to conferenceEventFallbackUrl. + fallback_password (str, optional): The password to send in the HTTP request to conferenceEventFallbackUrl. + tag (str, optional): A custom string that will be sent with this and all future callbacks unless overwritten by a future tag attribute or verb, or cleared. May be cleared by setting tag="". + Max length 256 characters. Defaults to None. + callback_timeout (str, optional): This is the timeout (in seconds) to use when delivering webhooks for the conference. + 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. + + Nested Verbs: + PlayAudio: (optional) + SpeakSentence: (optional) + StartRecording: (optional) + StopRecording: (optional) + PauseRecording: (optional) + ResumeRecording: (optional) + """ + self.name = name + self.mute = mute + self.hold = hold + self.call_ids_to_coach = call_ids_to_coach + self.conference_event_url = conference_event_url + self.conference_event_method = conference_event_method + self.conference_event_fallback_url = conference_event_fallback_url + self.conference_event_fallback_method = conference_event_fallback_method + self.username = username + self.password = password + self.fallback_username = fallback_username + self.fallback_password = fallback_password + self.tag = tag + self.callback_timeout = callback_timeout + self.audio_and_recording_verbs = audio_and_recording_verbs + super().__init__( + tag="Conference", + content=self.name, + nested_verbs=self.audio_and_recording_verbs) + + @property + def _attributes(self): + return { + "mute": self.mute, + "hold": self.hold, + "callIdsToCoach": self.call_ids_to_coach, + "conferenceEventUrl": self.conference_event_url, + "conferenceEventMethod": self.conference_event_method, + "conferenceEventFallbackUrl": self.conference_event_fallback_url, + "conferenceEventFallbackMethod": self.conference_event_fallback_method, + "username": self.username, + "password": self.password, + "fallbackUsername": self.fallback_username, + "fallbackPassword": self.fallback_password, + "tag": self.tag, + "callbackTimeout": self.callback_timeout, + } diff --git a/test/unit/bxml/test_conference.py b/test/unit/bxml/test_conference.py new file mode 100644 index 00000000..e2c98221 --- /dev/null +++ b/test/unit/bxml/test_conference.py @@ -0,0 +1,66 @@ +""" +test_conference.py + +Unit tests for the BXML verb + +@copyright Bandwidth Inc. +""" +import os +import pytest +import unittest + +from bandwidth.model.bxml.verb import Verb +from bandwidth.model.bxml.verbs import * + +class TestGather(unittest.TestCase): + + def setUp(self): + self.play_audio = PlayAudio( + audio_uri="https://audio.url/audio1.wav" + ) + + self.speak_sentence = SpeakSentence( + text='Hello there.' + ) + self.start_recording = StartRecording( + recording_available_url = "example.com", + recording_available_method = "POST", + username = "user", + password = "pass", + tag = "tag", + file_format = "wav", + multi_channel = "true" + ) + + self.conference = Conference( + name="conf1", + mute = "true", + hold = "false", + call_ids_to_coach = "example-call-id", + conference_event_url = "example.com/eventurl", + conference_event_method = "POST", + conference_event_fallback_url = "backupexample.com/eventurl", + conference_event_fallback_method = "POST", + username = "user", + password = "pass", + fallback_username = "user", + fallback_password = "pass", + tag = "tag", + callback_timeout = "5", + audio_and_recording_verbs=[self.play_audio, self.start_recording] + ) + + def test_to_bxml(self): + if os.environ['PYTHON_VERSION'] == '3.7': + expected = 'conf1https://audio.url/audio1.wav' + else: + expected = 'conf1https://audio.url/audio1.wav' + assert(expected == self.conference.to_bxml()) + + def test_add_verb(self): + if os.environ['PYTHON_VERSION'] == '3.7': + expected = 'conf1https://audio.url/audio1.wavHello there.' + else: + expected = 'conf1https://audio.url/audio1.wavHello there.' + self.conference.add_verb(self.speak_sentence) + assert(expected == self.conference.to_bxml()) From 79d27123c67ce244d149c806c2f265e32ca29d8d Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 4 Oct 2022 15:59:19 -0400 Subject: [PATCH 2/4] Update test_conference.py --- test/unit/bxml/test_conference.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/bxml/test_conference.py b/test/unit/bxml/test_conference.py index e2c98221..b94e0442 100644 --- a/test/unit/bxml/test_conference.py +++ b/test/unit/bxml/test_conference.py @@ -52,14 +52,14 @@ def setUp(self): def test_to_bxml(self): if os.environ['PYTHON_VERSION'] == '3.7': - expected = 'conf1https://audio.url/audio1.wav' + expected = 'conf1https://audio.url/audio1.wav' else: expected = 'conf1https://audio.url/audio1.wav' assert(expected == self.conference.to_bxml()) def test_add_verb(self): if os.environ['PYTHON_VERSION'] == '3.7': - expected = 'conf1https://audio.url/audio1.wavHello there.' + expected = 'conf1https://audio.url/audio1.wavHello there.' else: expected = 'conf1https://audio.url/audio1.wavHello there.' self.conference.add_verb(self.speak_sentence) From b42dfae7180bd5e09e883ea6e742aa4068c08f7d Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 4 Oct 2022 16:43:55 -0400 Subject: [PATCH 3/4] Update conference.py --- bandwidth/model/bxml/verbs/conference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bandwidth/model/bxml/verbs/conference.py b/bandwidth/model/bxml/verbs/conference.py index fb824f59..c17e7956 100644 --- a/bandwidth/model/bxml/verbs/conference.py +++ b/bandwidth/model/bxml/verbs/conference.py @@ -19,7 +19,7 @@ class Conference(Verb): def __init__( self, audio_and_recording_verbs: List[Union[PlayAudio, SpeakSentence, StartRecording, StopRecording, PauseRecording, ResumeRecording]] = [], - name: str=None, mute: str=None, + name: str, mute: str=None, hold: str=None, call_ids_to_coach: str=None, conference_event_url: str=None, conference_event_method: str=None, conference_event_fallback_url: str=None, conference_event_fallback_method: str=None, From 1051f728613011a9c0d71c39c902cf84d1b3555d Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 4 Oct 2022 16:46:47 -0400 Subject: [PATCH 4/4] Update conference.py --- bandwidth/model/bxml/verbs/conference.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bandwidth/model/bxml/verbs/conference.py b/bandwidth/model/bxml/verbs/conference.py index c17e7956..2c1dc49e 100644 --- a/bandwidth/model/bxml/verbs/conference.py +++ b/bandwidth/model/bxml/verbs/conference.py @@ -18,8 +18,8 @@ class Conference(Verb): def __init__( - self, audio_and_recording_verbs: List[Union[PlayAudio, SpeakSentence, StartRecording, StopRecording, PauseRecording, ResumeRecording]] = [], - name: str, mute: str=None, + self, name: str, + audio_and_recording_verbs: List[Union[PlayAudio, SpeakSentence, StartRecording, StopRecording, PauseRecording, ResumeRecording]] = [], mute: str=None, hold: str=None, call_ids_to_coach: str=None, conference_event_url: str=None, conference_event_method: str=None, conference_event_fallback_url: str=None, conference_event_fallback_method: str=None,