Skip to content

Commit

Permalink
Added interrupt audio and announce api. (#38916)
Browse files Browse the repository at this point in the history
* Added interrupt audio and announce api

* Added event validation in live test

* Added unit test

* updating the test

* fixing pylint errors

---------

Co-authored-by: Vinothini Dharmaraj <[email protected]>
  • Loading branch information
v-pivamshi and v-vdharmaraj authored Dec 30, 2024
1 parent 1820bd0 commit 5e2ca77
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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__()
Expand Down
Original file line number Diff line number Diff line change
@@ -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"}}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
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)
Loading

0 comments on commit 5e2ca77

Please sign in to comment.