diff --git a/sdk/communication/azure-communication-callautomation/assets.json b/sdk/communication/azure-communication-callautomation/assets.json index ba164cc72871..2cf984f5d7c9 100644 --- a/sdk/communication/azure-communication-callautomation/assets.json +++ b/sdk/communication/azure-communication-callautomation/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "python", "TagPrefix": "python/communication/azure-communication-callautomation", - "Tag": "python/communication/azure-communication-callautomation_bd0d24ba7b" + "Tag": "python/communication/azure-communication-callautomation_40e440aaba" } diff --git a/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/_call_connection_client.py b/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/_call_connection_client.py index c14c2c100e6f..b3c30891f06e 100644 --- a/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/_call_connection_client.py +++ b/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/_call_connection_client.py @@ -49,7 +49,8 @@ HoldRequest, UnholdRequest, StartMediaStreamingRequest, - StopMediaStreamingRequest + StopMediaStreamingRequest, + InterruptAudioAndAnnounceRequest, ) from ._generated.models._enums import RecognizeInputType from ._shared.auth_policy_utils import get_authentication_policy @@ -1138,3 +1139,40 @@ def stop_media_streaming( stop_media_streaming_request, **kwargs ) + + @distributed_trace + def interrupt_audio_and_announce( + self, + target_participant: "CommunicationIdentifier", + play_sources: List[Union['FileSource', 'TextSource', 'SsmlSource']], + *, + operation_context: Optional[str] = None, + **kwargs, + ) -> None: + """Interrupt audio and announce to specific participant(s) in this call. + + :param target_participant: The participant being added. + :type target_participant: ~azure.communication.callautomation.CommunicationIdentifier + :param play_sources: A PlaySource representing the source to play. + :type play_sources: list[~azure.communication.callautomation.FileSource] or + list[~azure.communication.callautomation.TextSource] or + list[~azure.communication.callautomation.SsmlSource] + :keyword operation_context: Value that can be used to track this call and its associated events. + :paramtype operation_context: str or None + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + + interrupt_audio_announce_request = InterruptAudioAndAnnounceRequest( + play_sources=[source._to_generated() for source in play_sources] if play_sources else None, # pylint: disable=protected-access + play_to=serialize_identifier(target_participant), + operation_context=operation_context, + kwargs=kwargs, + ) + + self._call_media_client.interrupt_audio_and_announce( + self._call_connection_id, + interrupt_audio_announce_request, + **kwargs + ) diff --git a/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/aio/_call_connection_client_async.py b/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/aio/_call_connection_client_async.py index fc43ec554c0f..d6a3b27b0850 100644 --- a/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/aio/_call_connection_client_async.py +++ b/sdk/communication/azure-communication-callautomation/azure/communication/callautomation/aio/_call_connection_client_async.py @@ -50,7 +50,8 @@ HoldRequest, UnholdRequest, StartMediaStreamingRequest, - StopMediaStreamingRequest + StopMediaStreamingRequest, + InterruptAudioAndAnnounceRequest ) from .._generated.models._enums import RecognizeInputType from .._shared.auth_policy_utils import get_authentication_policy @@ -1151,6 +1152,42 @@ async def stop_media_streaming( **kwargs ) + @distributed_trace_async + async def interrupt_audio_and_announce( + self, + target_participant: "CommunicationIdentifier", + play_sources: List[Union['FileSource', 'TextSource', 'SsmlSource']], + *, + operation_context: Optional[str] = None, + **kwargs, + ) -> None: + """Play media to specific participant(s) in this call. + + :param target_participant: The participant being added. + :type target_participant: ~azure.communication.callautomation.CommunicationIdentifier + :param play_sources: A PlaySource representing the source to play. + :type play_sources: list[~azure.communication.callautomation.FileSource] or + list[~azure.communication.callautomation.TextSource] or + list[~azure.communication.callautomation.SsmlSource] + :keyword operation_context: Value that can be used to track this call and its associated events. + :paramtype operation_context: str or None + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + interrupt_audio_announce_request = InterruptAudioAndAnnounceRequest( + play_sources=[source._to_generated() for source in play_sources] if play_sources else None, # pylint:disable=protected-access + play_to=serialize_identifier(target_participant), + operation_context=operation_context, + kwargs=kwargs, + ) + + self._call_media_client.interrupt_audio_and_announce( + self._call_connection_id, + interrupt_audio_announce_request, + **kwargs + ) + async def __aenter__(self) -> "CallConnectionClient": await self._client.__aenter__() diff --git a/sdk/communication/azure-communication-callautomation/tests/events/test_e2e_media_client.pyTestMediaAutomatedLiveTesttest_interrupt_audio_and_announce_in_a_call.event.json b/sdk/communication/azure-communication-callautomation/tests/events/test_e2e_media_client.pyTestMediaAutomatedLiveTesttest_interrupt_audio_and_announce_in_a_call.event.json new file mode 100644 index 000000000000..7d721408299f --- /dev/null +++ b/sdk/communication/azure-communication-callautomation/tests/events/test_e2e_media_client.pyTestMediaAutomatedLiveTesttest_interrupt_audio_and_announce_in_a_call.event.json @@ -0,0 +1 @@ +{"IncomingCall": {"to": {"kind": "communicationUser", "rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511"}}, "from": {"kind": "communicationUser", "rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510"}}, "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "callerDisplayName": "REDACTED", "incomingCallContext": "REDACTED", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921"}, "CallConnected": {"id": "192b4ccc-de4a-41b8-8883-71a9f7461b71", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.CallConnected", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 0, "message": ""}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.CallConnected"}, "time": "2024-12-23T22:29:23.8584612+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "ParticipantsUpdated": {"id": "0c11fe17-bf61-45bf-8d81-8f5eff03c72a", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.ParticipantsUpdated", "data": {"participants": [{"identifier": {"rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510", "kind": "communicationUser", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-25b6-f883-084822008510"}}, "isMuted": false, "isOnHold": false}, {"identifier": {"rawId": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511", "kind": "communicationUser", "communicationUser": {"id": "8:acs:6d889502-3d7a-41a8-befa-d21fd80e8767_00000024-9585-2606-f883-084822008511"}}, "isMuted": false, "isOnHold": false}], "sequenceNumber": 5, "resultInformation": {"code": 200, "subCode": 0, "message": ""}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.ParticipantsUpdated"}, "time": "2024-12-23T22:29:37.1441684+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioStarted": {"id": "22a42540-9faf-4e13-a271-869e12cd42d8", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioStarted", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioStarted"}, "time": "2024-12-23T22:29:28.8986091+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioPaused": {"id": "bbc2ebc9-549b-4b10-b50b-df112e5efda7", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioPaused", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioPaused"}, "time": "2024-12-23T22:29:30.8983666+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "PlayStarted": {"id": "8c7726d8-5ea5-4ff1-a2f7-194b5583d2bf", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.PlayStarted", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.PlayStarted"}, "time": "2024-12-23T22:29:30.9169166+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "PlayCompleted": {"id": "ec7faa38-8313-4869-a774-14421197f02f", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.PlayCompleted", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.PlayCompleted"}, "time": "2024-12-23T22:29:35.1788036+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioResumed": {"id": "ae45dbbb-f42e-401b-8c96-9e2853ee672c", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioResumed", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 200, "subCode": 0, "message": "Action completed successfully."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioResumed"}, "time": "2024-12-23T22:29:35.1865892+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "HoldAudioCompleted": {"id": "70b82aa5-a093-4d40-9e2b-147c45dff10e", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.HoldAudioCompleted", "data": {"operationContext": "hold_add_target_participant", "resultInformation": {"code": 400, "subCode": 8508, "message": "Action falied, the operation was cancelled."}, "version": "2024-09-01-preview", "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.HoldAudioCompleted"}, "time": "2024-12-23T22:29:37.0473909+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}, "CallDisconnected": {"id": "ba730173-a88b-4b70-94ba-c31fd6bf5d8d", "source": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09", "type": "Microsoft.Communication.CallDisconnected", "data": {"version": "2024-09-01-preview", "resultInformation": {"code": 200, "subCode": 7000, "message": "The conversation has ended. DiagCode: 0#7000.@"}, "callConnectionId": "1f002180-3e67-4000-a767-59f98e264a09", "serverCallId": "aHR0cHM6Ly9hcGkuZmxpZ2h0cHJveHkuc2t5cGUuY29tL2FwaS92Mi9jcC9jb252LXVzd2UtMDUtcHJvZC1ha3MuY29udi5za3lwZS5jb20vY29udi95TDZucnVHNWEwT0VlV3RnNUVQS1VnP2k9MTAtMTI4LTE3Ny03MSZlPTYzODY5OTgwMjE2NTgwMDIyNg==", "correlationId": "3d8073c1-8559-4f72-a473-9fadafb1f921", "publicEventType": "Microsoft.Communication.CallDisconnected"}, "time": "2024-12-23T22:29:39.5639151+00:00", "specversion": "1.0", "datacontenttype": "application/json", "subject": "calling/callConnections/1f002180-3e67-4000-a767-59f98e264a09"}} \ No newline at end of file diff --git a/sdk/communication/azure-communication-callautomation/tests/test_call_media_client.py b/sdk/communication/azure-communication-callautomation/tests/test_call_media_client.py index 66670c6efcfb..828da761fbf9 100644 --- a/sdk/communication/azure-communication-callautomation/tests/test_call_media_client.py +++ b/sdk/communication/azure-communication-callautomation/tests/test_call_media_client.py @@ -30,7 +30,8 @@ HoldRequest, UnholdRequest, StartMediaStreamingRequest, - StopMediaStreamingRequest + StopMediaStreamingRequest, + InterruptAudioAndAnnounceRequest ) from azure.communication.callautomation._generated.models._enums import RecognizeInputType, DtmfTone from unittest.mock import Mock @@ -718,4 +719,55 @@ def test_stop_media_streaming_with_no_param(self): mock_stop_media_streaming.assert_called_once() actual_call_connection_id = mock_stop_media_streaming.call_args[0][0] - self.assertEqual(self.call_connection_id,actual_call_connection_id) \ No newline at end of file + self.assertEqual(self.call_connection_id,actual_call_connection_id) + + def test_interrupt_audio_and_announce(self): + mock_hold = Mock() + mock_interrupt_audio_and_announce = Mock() + mock_unhold = Mock() + self.call_media_operations.hold = mock_hold + self.call_media_operations.interrupt_audio_and_announce = mock_interrupt_audio_and_announce + self.call_media_operations.unhold = mock_unhold + self.call_media_operations.hold = mock_hold + play_source = FileSource(url=self.url) + operation_context = "context" + + self.call_connection_client.hold( + target_participant=self.target_user, play_source=play_source, operation_context=operation_context + ) + + expected_hold_request = HoldRequest( + target_participant=[serialize_identifier(self.target_user)], + play_source_info=play_source._to_generated(), + operation_context=operation_context, + ) + mock_hold.assert_called_once() + actual_hold_request = mock_hold.call_args[0][1] + + self.assertEqual(expected_hold_request.play_source_info.file.uri, actual_hold_request.play_source_info.file.uri) + self.assertEqual(expected_hold_request.play_source_info.kind, actual_hold_request.play_source_info.kind) + self.assertEqual(expected_hold_request.operation_context, actual_hold_request.operation_context) + + play_sources = [FileSource(url=self.url), TextSource(text='test test test')] + self.call_connection_client.interrupt_audio_and_announce(target_participant=self.target_user, play_sources=play_sources) + + expected_interrupt_audio_announce_request = InterruptAudioAndAnnounceRequest( + play_sources=[play_source._to_generated()], + play_to=serialize_identifier(self.target_user), + operation_context=operation_context, + ) + mock_interrupt_audio_and_announce.assert_called_once() + actual_interrupt_audio_and_announce_request = mock_interrupt_audio_and_announce.call_args[0][1] + + self.assertEqual(expected_interrupt_audio_announce_request.play_sources[0].kind, actual_interrupt_audio_and_announce_request.play_sources[0].kind) + self.assertEqual(expected_interrupt_audio_announce_request.play_to, actual_interrupt_audio_and_announce_request.play_to) + + self.call_connection_client.unhold(target_participant=self.target_user, operation_context=operation_context) + + expected_hold_request = UnholdRequest( + target_participant=serialize_identifier(self.target_user), operation_context=operation_context + ) + mock_unhold.assert_called_once() + actual_hold_request = mock_unhold.call_args[0][1] + + self.assertEqual(expected_hold_request.operation_context, actual_hold_request.operation_context) \ No newline at end of file diff --git a/sdk/communication/azure-communication-callautomation/tests/test_e2e_media_client.py b/sdk/communication/azure-communication-callautomation/tests/test_e2e_media_client.py index 506e20fbc819..579d1a652eed 100644 --- a/sdk/communication/azure-communication-callautomation/tests/test_e2e_media_client.py +++ b/sdk/communication/azure-communication-callautomation/tests/test_e2e_media_client.py @@ -742,5 +742,81 @@ def test_play_with_invalid_and_valid_file_sources_with_play_media(self): if play_failed_event_to_target is None: raise ValueError("PlayFailed event is None") + self.terminate_call(unique_id) + return + + @recorded_by_proxy + def test_interrupt_audio_and_announce_in_a_call(self): + + # try to establish the call + caller = self.identity_client.create_user() + target = self.identity_client.create_user() + unique_id, call_connection, _ = self.establish_callconnection_voip(caller, target) + + # check returned events + connected_event = self.check_for_event( + "CallConnected", call_connection._call_connection_id, timedelta(seconds=15) + ) + participant_updated_event = self.check_for_event( + "ParticipantsUpdated", call_connection._call_connection_id, timedelta(seconds=15) + ) + + if connected_event is None: + raise ValueError("Caller CallConnected event is None") + if participant_updated_event is None: + raise ValueError("Caller ParticipantsUpdated event is None") + play_source = FileSource(url=self.file_source_url) + + # Hold participant + call_connection.hold(target_participant=target, play_source=play_source, operation_context="hold_add_target_participant") + time.sleep(2) + # check returned events + hold_audio_started_event = self.check_for_event( + "HoldAudioStarted", call_connection._call_connection_id, timedelta(seconds=15) + ) + if hold_audio_started_event is None: + raise ValueError("Caller HoldAudioStarted event is None") + + get_participant_result = call_connection.get_participant(target) + if get_participant_result is None: + raise ValueError("Invalid get_participant_result") + + if get_participant_result.is_on_hold is False: + raise ValueError("Failed to hold participant") + play_multiple_file_source = [ + FileSource(url=self.file_source_url) + ] + call_connection.interrupt_audio_and_announce(target_participant=target, play_sources=play_multiple_file_source) + + # check returned events + hold_audio_paused_event = self.check_for_event( + "HoldAudioPaused", call_connection._call_connection_id, timedelta(seconds=15) + ) + if hold_audio_paused_event is None: + raise ValueError("Caller HoldAudioPaused event is None") + + hold_audio_resumed_event = self.check_for_event( + "HoldAudioResumed", call_connection._call_connection_id, timedelta(seconds=15) + ) + if hold_audio_resumed_event is None: + raise ValueError("Caller HoldAudioResumed event is None") + + # Unhold participant + call_connection.unhold(target, operation_context="unhold_add_target_participant") + time.sleep(2) + hold_audio_completed_event = self.check_for_event( + "HoldAudioCompleted", call_connection._call_connection_id, timedelta(seconds=15) + ) + if hold_audio_completed_event is None: + raise ValueError("Caller HoldAudioCompleted event is None") + + get_participant_result = call_connection.get_participant(target) + + if get_participant_result is None: + raise ValueError("Invalid get_participant_result") + + if get_participant_result.is_on_hold is True: + raise ValueError("Failed to unhold participant") + self.terminate_call(unique_id) return \ No newline at end of file