diff --git a/sdk/communication/Azure.Communication.CallAutomation/api/Azure.Communication.CallAutomation.netstandard2.0.cs b/sdk/communication/Azure.Communication.CallAutomation/api/Azure.Communication.CallAutomation.netstandard2.0.cs index e7fe15d93109..9a6108f88e7e 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/api/Azure.Communication.CallAutomation.netstandard2.0.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/api/Azure.Communication.CallAutomation.netstandard2.0.cs @@ -190,7 +190,7 @@ public static partial class CallAutomationModelFactory public static Azure.Communication.CallAutomation.CallConnected CallConnected(string callConnectionId = null, string serverCallId = null, string correlationId = null, string operationContext = null) { throw null; } public static Azure.Communication.CallAutomation.CallConnectionProperties CallConnectionProperties(string callConnectionId = null, string serverCallId = null, System.Collections.Generic.IEnumerable targets = null, Azure.Communication.CallAutomation.CallConnectionState callConnectionState = default(Azure.Communication.CallAutomation.CallConnectionState), System.Uri callbackUri = null, Azure.Communication.CommunicationIdentifier sourceIdentity = null, Azure.Communication.PhoneNumberIdentifier sourceCallerIdNumber = null, string sourceDisplayName = null, Azure.Communication.CommunicationUserIdentifier answeredBy = null, string mediaSubscriptionId = null, string dataSubscriptionId = null) { throw null; } public static Azure.Communication.CallAutomation.CallDisconnected CallDisconnected(string callConnectionId = null, string serverCallId = null, string correlationId = null, string operationContext = null) { throw null; } - public static Azure.Communication.CallAutomation.CallParticipant CallParticipant(Azure.Communication.CommunicationIdentifier identifier = null, bool isMuted = false) { throw null; } + public static Azure.Communication.CallAutomation.CallParticipant CallParticipant(Azure.Communication.CommunicationIdentifier identifier = null, bool isMuted = false, bool isOnHold = false) { throw null; } public static Azure.Communication.CallAutomation.CallTransferAccepted CallTransferAccepted(string callConnectionId = null, string serverCallId = null, string correlationId = null, string operationContext = null, Azure.Communication.CallAutomation.ResultInformation resultInformation = null, Azure.Communication.CommunicationIdentifier transferee = null, Azure.Communication.CommunicationIdentifier transferTarget = null) { throw null; } public static Azure.Communication.CallAutomation.CallTransferFailed CallTransferFailed(string callConnectionId = null, string serverCallId = null, string correlationId = null, string operationContext = null, Azure.Communication.CallAutomation.ResultInformation resultInformation = null) { throw null; } public static Azure.Communication.CallAutomation.CancelAddParticipantFailed CancelAddParticipantFailed(string callConnectionId = null, string serverCallId = null, string correlationId = null, string invitationId = null, Azure.Communication.CallAutomation.ResultInformation resultInformation = null, string operationContext = null) { throw null; } @@ -204,6 +204,7 @@ public static partial class CallAutomationModelFactory public static Azure.Communication.CallAutomation.CreateCallFailed CreateCallFailed(string callConnectionId = null, string serverCallId = null, string correlationId = null, Azure.Communication.CallAutomation.ResultInformation resultInformation = null, string operationContext = null) { throw null; } public static Azure.Communication.CallAutomation.CreateCallResult CreateCallResult(Azure.Communication.CallAutomation.CallConnection callConnection = null, Azure.Communication.CallAutomation.CallConnectionProperties callConnectionProperties = null) { throw null; } public static Azure.Communication.CallAutomation.DtmfResult DtmfResult(System.Collections.Generic.IEnumerable tones = null) { throw null; } + public static Azure.Communication.CallAutomation.HoldFailed HoldFailed(string callConnectionId = null, string serverCallId = null, string correlationId = null, string operationContext = null, Azure.Communication.CallAutomation.ResultInformation resultInformation = null) { throw null; } public static Azure.Communication.CallAutomation.MuteParticipantResult MuteParticipantResult(string operationContext = null) { throw null; } public static Azure.Communication.CallAutomation.ParticipantsUpdated ParticipantsUpdated(string callConnectionId = null, string serverCallId = null, string correlationId = null, System.Collections.Generic.IEnumerable participants = null, int sequenceNumber = 0) { throw null; } public static Azure.Communication.CallAutomation.PlayCanceled PlayCanceled(string callConnectionId = null, string serverCallId = null, string correlationId = null, string operationContext = null) { throw null; } @@ -361,6 +362,8 @@ protected CallMedia() { } public virtual string CallConnectionId { get { throw null; } } public virtual Azure.Response CancelAllMediaOperations(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> CancelAllMediaOperationsAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response Hold(Azure.Communication.CallAutomation.HoldOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task HoldAsync(Azure.Communication.CallAutomation.HoldOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response Play(Azure.Communication.CallAutomation.PlayOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response Play(Azure.Communication.CallAutomation.PlaySource playSource, System.Collections.Generic.IEnumerable playTo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> PlayAsync(Azure.Communication.CallAutomation.PlayOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -377,7 +380,9 @@ protected CallMedia() { } public virtual Azure.Response StartContinuousDtmfRecognition(Azure.Communication.CommunicationIdentifier targetParticipant, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task StartContinuousDtmfRecognitionAsync(Azure.Communication.CallAutomation.ContinuousDtmfRecognitionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task StartContinuousDtmfRecognitionAsync(Azure.Communication.CommunicationIdentifier targetParticipant, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.ObsoleteAttribute("This operations is deprecated, please us Hold instead.")] public virtual Azure.Response StartHoldMusic(Azure.Communication.CallAutomation.StartHoldMusicOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.ObsoleteAttribute("This operations is deprecated, please us HoldAsync instead.")] public virtual System.Threading.Tasks.Task StartHoldMusicAsync(Azure.Communication.CallAutomation.StartHoldMusicOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response StartRecognizing(Azure.Communication.CallAutomation.CallMediaRecognizeOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task> StartRecognizingAsync(Azure.Communication.CallAutomation.CallMediaRecognizeOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -387,10 +392,14 @@ protected CallMedia() { } public virtual Azure.Response StopContinuousDtmfRecognition(Azure.Communication.CommunicationIdentifier targetParticipant, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task StopContinuousDtmfRecognitionAsync(Azure.Communication.CallAutomation.ContinuousDtmfRecognitionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task StopContinuousDtmfRecognitionAsync(Azure.Communication.CommunicationIdentifier targetParticipant, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.ObsoleteAttribute("This operations is deprecated, please us Unhold instead.")] public virtual Azure.Response StopHoldMusic(Azure.Communication.CallAutomation.StopHoldMusicOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + [System.ObsoleteAttribute("This operations is deprecated, please us UnholdAsync instead.")] public virtual System.Threading.Tasks.Task StopHoldMusicAsync(Azure.Communication.CallAutomation.StopHoldMusicOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response StopTranscription(Azure.Communication.CallAutomation.StopTranscriptionOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task StopTranscriptionAsync(Azure.Communication.CallAutomation.StopTranscriptionOptions options = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response Unhold(Azure.Communication.CallAutomation.UnholdOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task UnholdAsync(Azure.Communication.CallAutomation.UnholdOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual Azure.Response UpdateTranscription(string locale, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.Task UpdateTranscriptionAsync(string locale, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } @@ -848,6 +857,20 @@ public GroupCallLocator(string id) { } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } + public partial class HoldFailed : Azure.Communication.CallAutomation.CallAutomationEventBase + { + internal HoldFailed() { } + public Azure.Communication.CallAutomation.MediaEventReasonCode ReasonCode { get { throw null; } } + public static Azure.Communication.CallAutomation.HoldFailed Deserialize(string content) { throw null; } + } + public partial class HoldOptions + { + public HoldOptions(Azure.Communication.CommunicationIdentifier targetParticipant) { } + public System.Uri OperationCallbackUri { get { throw null; } set { } } + public string OperationContext { get { throw null; } set { } } + public Azure.Communication.CallAutomation.PlaySource PlaySourceInfo { get { throw null; } set { } } + public Azure.Communication.CommunicationIdentifier TargetParticipant { get { throw null; } } + } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct MediaEventReasonCode : System.IEquatable { @@ -1594,6 +1617,12 @@ public TransferToParticipantOptions(Azure.Communication.PhoneNumberIdentifier ta public Azure.Communication.CommunicationIdentifier Target { get { throw null; } } public Azure.Communication.CommunicationIdentifier Transferee { get { throw null; } set { } } } + public partial class UnholdOptions + { + public UnholdOptions(Azure.Communication.CommunicationIdentifier targetParticipant) { } + public string OperationContext { get { throw null; } set { } } + public Azure.Communication.CommunicationIdentifier TargetParticipant { get { throw null; } } + } public partial class UnmuteParticipantOptions { public UnmuteParticipantOptions(Azure.Communication.CommunicationIdentifier targetParticipant) { } diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/CallMedia.cs b/sdk/communication/Azure.Communication.CallAutomation/src/CallMedia.cs index ebb9c33bd4b7..bc151e39f2c3 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/src/CallMedia.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/src/CallMedia.cs @@ -393,6 +393,7 @@ public virtual Response StartRecognizing(CallMe /// The options. /// /// + [Obsolete("This operations is deprecated, please us Hold instead.")] public virtual Response StartHoldMusic(StartHoldMusicOptions options, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(StartHoldMusic)}"); @@ -402,11 +403,11 @@ public virtual Response StartHoldMusic(StartHoldMusicOptions options, Cancellati //ToDo: Media team needs to fix the options.Loop since StartHoldMusicRequestInternal does not have Lopp anymore. // and work on the StartHoldMusicRequestInternal.operationCallbackUri var request = new StartHoldMusicRequestInternal( - CommunicationIdentifierSerializer.Serialize(options.TargetParticipant), - TranslatePlaySourceToInternal(options.PlaySourceInfo), - options.OperationContext, - null - ); + CommunicationIdentifierSerializer.Serialize(options.TargetParticipant)) + { + OperationContext = options.OperationContext, + PlaySourceInfo = TranslatePlaySourceToInternal(options.PlaySourceInfo), + }; return CallMediaRestClient.StartHoldMusic(CallConnectionId, request, cancellationToken: cancellationToken); } @@ -423,19 +424,19 @@ public virtual Response StartHoldMusic(StartHoldMusicOptions options, Cancellati /// The options. /// /// + [Obsolete("This operations is deprecated, please us HoldAsync instead.")] public virtual async Task StartHoldMusicAsync(StartHoldMusicOptions options, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(StartHoldMusicAsync)}"); scope.Start(); try { - //ToDo: Media team needs to fix the options.Loop since StartHoldMusicRequestInternal does not have Lopp anymore. - // and work on the StartHoldMusicRequestInternal.operationCallbackUri var request = new StartHoldMusicRequestInternal( - CommunicationIdentifierSerializer.Serialize(options.TargetParticipant), - TranslatePlaySourceToInternal(options.PlaySourceInfo), - options.OperationContext, - null); + CommunicationIdentifierSerializer.Serialize(options.TargetParticipant)) + { + OperationContext = options.OperationContext, + PlaySourceInfo = TranslatePlaySourceToInternal(options.PlaySourceInfo), + }; return await CallMediaRestClient.StartHoldMusicAsync(CallConnectionId, request, cancellationToken: cancellationToken).ConfigureAwait(false); } @@ -452,6 +453,7 @@ public virtual async Task StartHoldMusicAsync(StartHoldMusicOptions op /// The options. /// /// + [Obsolete("This operations is deprecated, please us UnholdAsync instead.")] public virtual async Task StopHoldMusicAsync(StopHoldMusicOptions options, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(StopHoldMusicAsync)}"); @@ -475,6 +477,7 @@ public virtual async Task StopHoldMusicAsync(StopHoldMusicOptions opti /// The options. /// /// + [Obsolete("This operations is deprecated, please us Unhold instead.")] public virtual Response StopHoldMusic(StopHoldMusicOptions options, CancellationToken cancellationToken = default) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(StopHoldMusicAsync)}"); @@ -492,6 +495,110 @@ public virtual Response StopHoldMusic(StopHoldMusicOptions options, Cancellation } } + /// + /// Hold participant from the call. + /// + /// The options. + /// + /// + public virtual async Task HoldAsync(HoldOptions options, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(StartHoldMusicAsync)}"); + scope.Start(); + try + { + var request = new HoldRequestInternal( + CommunicationIdentifierSerializer.Serialize(options.TargetParticipant)) + { + OperationContext = options.OperationContext, + PlaySourceInfo = TranslatePlaySourceToInternal(options.PlaySourceInfo), + OperationCallbackUri = options.OperationCallbackUri?.AbsoluteUri, + }; + + return await CallMediaRestClient.HoldAsync(CallConnectionId, request, cancellationToken: cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Hold participant from the call. + /// + /// The options. + /// + /// + public virtual Response Hold(HoldOptions options, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(Hold)}"); + scope.Start(); + try + { + var request = new HoldRequestInternal( + CommunicationIdentifierSerializer.Serialize(options.TargetParticipant)) + { + OperationContext = options.OperationContext, + PlaySourceInfo = TranslatePlaySourceToInternal(options.PlaySourceInfo), + OperationCallbackUri = options.OperationCallbackUri?.AbsoluteUri, + }; + + return CallMediaRestClient.Hold(CallConnectionId, request, cancellationToken: cancellationToken); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Remove hold from participant. + /// + /// The options. + /// + /// + public virtual async Task UnholdAsync(UnholdOptions options, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(StopHoldMusicAsync)}"); + scope.Start(); + try + { + var request = new UnholdRequestInternal(CommunicationIdentifierSerializer.Serialize(options.TargetParticipant)); + + return await CallMediaRestClient.UnholdAsync(CallConnectionId, request, cancellationToken: cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + + /// + /// Remove hold from participant. + /// + /// The options. + /// + /// + public virtual Response Unhold(UnholdOptions options, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(CallMedia)}.{nameof(StopHoldMusicAsync)}"); + scope.Start(); + try + { + var request = new UnholdRequestInternal(CommunicationIdentifierSerializer.Serialize(options.TargetParticipant)); + + return CallMediaRestClient.Unhold(CallConnectionId, request, cancellationToken: cancellationToken); + } + catch (Exception ex) + { + scope.Failed(ex); + throw; + } + } + private static RecognizeRequestInternal CreateRecognizeRequest(CallMediaRecognizeOptions recognizeOptions) { if (recognizeOptions == null) diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Generated/Models/HoldFailed.Serialization.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Generated/Models/HoldFailed.Serialization.cs new file mode 100644 index 000000000000..b4d847a33e73 --- /dev/null +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Generated/Models/HoldFailed.Serialization.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; + +namespace Azure.Communication.CallAutomation +{ + public partial class HoldFailed + { + internal static HoldFailed DeserializeHoldFailed(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string operationContext = default; + ResultInformation resultInformation = default; + string callConnectionId = default; + string serverCallId = default; + string correlationId = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("operationContext"u8)) + { + operationContext = property.Value.GetString(); + continue; + } + if (property.NameEquals("resultInformation"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + resultInformation = ResultInformation.DeserializeResultInformation(property.Value); + continue; + } + if (property.NameEquals("callConnectionId"u8)) + { + callConnectionId = property.Value.GetString(); + continue; + } + if (property.NameEquals("serverCallId"u8)) + { + serverCallId = property.Value.GetString(); + continue; + } + if (property.NameEquals("correlationId"u8)) + { + correlationId = property.Value.GetString(); + continue; + } + } + return new HoldFailed(operationContext, resultInformation, callConnectionId, serverCallId, correlationId); + } + } +} diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Generated/Models/HoldFailed.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Generated/Models/HoldFailed.cs index a61ea1b2d36b..e0721196e11e 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/src/Generated/Models/HoldFailed.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Generated/Models/HoldFailed.cs @@ -8,37 +8,11 @@ namespace Azure.Communication.CallAutomation { /// The HoldFailed. - internal partial class HoldFailed + public partial class HoldFailed { /// Initializes a new instance of . internal HoldFailed() { } - - /// Initializes a new instance of . - /// Used by customers when calling mid-call actions to correlate the request to the response event. - /// Contains the resulting SIP code, sub-code and message. - /// Call connection ID. - /// Server call ID. - /// Correlation ID for event to call correlation. Also called ChainId for skype chain ID. - internal HoldFailed(string operationContext, ResultInformation resultInformation, string callConnectionId, string serverCallId, string correlationId) - { - OperationContext = operationContext; - ResultInformation = resultInformation; - CallConnectionId = callConnectionId; - ServerCallId = serverCallId; - CorrelationId = correlationId; - } - - /// Used by customers when calling mid-call actions to correlate the request to the response event. - public string OperationContext { get; } - /// Contains the resulting SIP code, sub-code and message. - public ResultInformation ResultInformation { get; } - /// Call connection ID. - public string CallConnectionId { get; } - /// Server call ID. - public string ServerCallId { get; } - /// Correlation ID for event to call correlation. Also called ChainId for skype chain ID. - public string CorrelationId { get; } } } diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallAutomationModelFactory.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallAutomationModelFactory.cs index 12c61079f779..fd15396c8f5d 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallAutomationModelFactory.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallAutomationModelFactory.cs @@ -20,6 +20,7 @@ namespace Azure.Communication.CallAutomation [CodeGenSuppress("RecordingStateChanged", typeof(string), typeof(RecordingState), typeof(DateTimeOffset?), typeof(RecordingType?), typeof(string), typeof(string), typeof(string))] [CodeGenSuppress("SendDtmfTonesCompleted", typeof(string), typeof(ResultInformation), typeof(string), typeof(string), typeof(string))] [CodeGenSuppress("SendDtmfTonesFailed", typeof(string), typeof(ResultInformation), typeof(string), typeof(string), typeof(string))] + [CodeGenSuppress("HoldFailed", typeof(string), typeof(ResultInformation), typeof(string), typeof(string), typeof(string))] [CodeGenModel("CommunicationCallAutomationModelFactory")] public static partial class CallAutomationModelFactory { @@ -74,10 +75,11 @@ public static CallConnectionProperties CallConnectionProperties( /// Initializes a new instance of CallParticipant. /// The communication identifier. /// Is participant muted. + /// Is participant on hold. /// A new instance for mocking. - public static CallParticipant CallParticipant(CommunicationIdentifier identifier = default, bool isMuted = default) + public static CallParticipant CallParticipant(CommunicationIdentifier identifier = default, bool isMuted = default, bool isOnHold = default) { - return new CallParticipant(identifier, isMuted); + return new CallParticipant(identifier, isMuted, isOnHold); } /// Initializes a new instance of CallParticipant. @@ -514,5 +516,17 @@ public static SendDtmfTonesFailed SendDtmfTonesFailed(string callConnectionId = return new SendDtmfTonesFailed(internalObject); } + + /// Initializes a new instance of HoldFailed. + /// Used by customers when calling mid-call actions to correlate the request to the response event. + /// Contains the resulting SIP code, sub-code and message. + /// Call connection ID. + /// Server call ID. + /// Correlation ID for event to call correlation. Also called ChainId for skype chain ID. + /// A new instance for mocking. + public static HoldFailed HoldFailed(string callConnectionId = null, string serverCallId = null, string correlationId = null, string operationContext = null, ResultInformation resultInformation = null) + { + return new HoldFailed(operationContext, resultInformation, callConnectionId, serverCallId, correlationId); + } } } diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallParticipant.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallParticipant.cs index feee88c5031d..349f0bdb3ab2 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallParticipant.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Models/CallParticipant.cs @@ -9,10 +9,12 @@ public class CallParticipant /// Initializes a new instance of CallParticipant. /// The communication identifier. /// Is participant muted. - internal CallParticipant(CommunicationIdentifier identifier, bool isMuted) + /// Is participant on hold. + internal CallParticipant(CommunicationIdentifier identifier, bool isMuted, bool isOnHold) { Identifier = identifier; IsMuted = isMuted; + IsOnHold = isOnHold; } /// Initializes a new instance of CallParticipant. @@ -21,6 +23,7 @@ internal CallParticipant(CallParticipantInternal callParticipantInternal) { Identifier = CommunicationIdentifierSerializer.Deserialize(callParticipantInternal.Identifier); IsMuted = (bool)callParticipantInternal.IsMuted; + IsOnHold = callParticipantInternal.IsOnHold.GetValueOrDefault(false); } /// The communication identifier. diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Models/Events/CallAutomationEventParser.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Models/Events/CallAutomationEventParser.cs index 9efa05fe23bd..63d7eed97bb3 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/src/Models/Events/CallAutomationEventParser.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Models/Events/CallAutomationEventParser.cs @@ -154,6 +154,8 @@ private static CallAutomationEventBase Deserialize(string eventData, string type return AnswerFailed.Deserialize(eventData); case nameof(CreateCallFailed): return CreateCallFailed.Deserialize(eventData); + case nameof(HoldFailed): + return HoldFailed.Deserialize(eventData); #region Dialog case nameof(DialogCompleted): return DialogCompleted.Deserialize(eventData); diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Models/Events/HoldFailed.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Models/Events/HoldFailed.cs new file mode 100644 index 000000000000..8e0839ace51b --- /dev/null +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Models/Events/HoldFailed.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Communication.CallAutomation +{ + /// + /// The Hold Failed event. + /// + [CodeGenModel("HoldFailed", Usage = new string[] { "output" }, Formats = new string[] { "json" })] + public partial class HoldFailed : CallAutomationEventBase + { + /// + /// Reason code. + /// + public MediaEventReasonCode ReasonCode { get; internal set; } + + /// Initializes a new instance of HoldFailed. + /// Call connection ID. + /// Server call ID. + /// Correlation ID for event to call correlation. Also called ChainId for skype chain ID. + /// Used by customers when calling mid-call actions to correlate the request to the response event. + /// Contains the resulting SIP code/sub-code and message from NGC services. + internal HoldFailed(string operationContext, ResultInformation resultInformation, string callConnectionId, string serverCallId, string correlationId) + { + CallConnectionId = callConnectionId; + ServerCallId = serverCallId; + CorrelationId = correlationId; + OperationContext = operationContext; + ResultInformation = resultInformation; + ReasonCode = new MediaEventReasonCode(resultInformation.SubCode.ToString()); + } + + /// + /// Deserialize event. + /// + /// The json content. + /// The new object. + public static HoldFailed Deserialize(string content) + { + using var document = JsonDocument.Parse(content); + JsonElement element = document.RootElement; + + return DeserializeHoldFailed(element); + } + } +} diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Models/HoldOptions.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Models/HoldOptions.cs new file mode 100644 index 000000000000..bfaec92d42f6 --- /dev/null +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Models/HoldOptions.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Communication.CallAutomation +{ + /// + /// Options for the Hold Request. + /// + public class HoldOptions + { + /// + /// Creates a new HoldOptions object. + /// + public HoldOptions(CommunicationIdentifier targetParticipant) + { + TargetParticipant = targetParticipant; + } + + /// + /// The participant that is going to be put on hold. + /// + public CommunicationIdentifier TargetParticipant { get; } + + /// + /// Prompt to play while on hold. + /// + public PlaySource PlaySourceInfo { get; set; } + + /// + /// The operation context to correlate the request to the response event. + /// + public string OperationContext { get; set; } + + /// + /// The callback URI that overrides the default callback URI set by CreateCall/AnswerCall for this operation. + /// This setup is per-action. If this is not set, the default callback URI set by CreateCall/AnswerCall will be used. + /// + public Uri OperationCallbackUri { get; set; } + } +} diff --git a/sdk/communication/Azure.Communication.CallAutomation/src/Models/UnholdOptions.cs b/sdk/communication/Azure.Communication.CallAutomation/src/Models/UnholdOptions.cs new file mode 100644 index 000000000000..47c2dd5ada6b --- /dev/null +++ b/sdk/communication/Azure.Communication.CallAutomation/src/Models/UnholdOptions.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.Communication.CallAutomation +{ + /// + /// Options for the Hold Request. + /// + public class UnholdOptions + { + /// + /// Creates a new UnholdOptions object. + /// + public UnholdOptions(CommunicationIdentifier targetParticipant) + { + TargetParticipant = targetParticipant; + } + + /// + /// The participant that is currently on hold. + /// + public CommunicationIdentifier TargetParticipant { get; } + + /// + /// The operation context. + /// + public string OperationContext { get; set; } + } +} diff --git a/sdk/communication/Azure.Communication.CallAutomation/tests/CallMedias/CallMediaTests.cs b/sdk/communication/Azure.Communication.CallAutomation/tests/CallMedias/CallMediaTests.cs index 13dc1a96ef9b..c81a7f59b54e 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/tests/CallMedias/CallMediaTests.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/tests/CallMedias/CallMediaTests.cs @@ -143,7 +143,7 @@ public class CallMediaTests : CallAutomationTestBase private static readonly StartHoldMusicOptions _startHoldMusicOptions = new StartHoldMusicOptions(new CommunicationUserIdentifier("targetUserId"), _textSource) { - OperationContext = "operationContext" + OperationContext = "operationContext", }; private static readonly StopHoldMusicOptions _stopHoldMusicOptions = new StopHoldMusicOptions(new CommunicationUserIdentifier("targetUserId")) @@ -151,6 +151,24 @@ public class CallMediaTests : CallAutomationTestBase OperationContext = "operationContext" }; + private static readonly HoldOptions _holdOptions = new HoldOptions(new CommunicationUserIdentifier("targetUserId")) + { + OperationContext = "operationContext", + PlaySourceInfo = _textSource, + OperationCallbackUri = new Uri("https://localhost") + }; + + private static readonly HoldOptions _holdOptionsNoMusic = new HoldOptions(new CommunicationUserIdentifier("targetUserId")) + { + OperationContext = "operationContext", + OperationCallbackUri = new Uri("https://localhost") + }; + + private static readonly UnholdOptions _unholdOptions = new UnholdOptions(new CommunicationUserIdentifier("targetUserId")) + { + OperationContext = "operationContext" + }; + private static CallMedia? _callMedia; [SetUp] @@ -782,6 +800,7 @@ public void HoldMusicOperations_Return200Ok(Func operation) }; } + [Obsolete] private static IEnumerable TestData_HoldOperationsAsync() { return new[] @@ -792,11 +811,20 @@ public void HoldMusicOperations_Return200Ok(Func operation) }, new Func>?[] { - callMedia => callMedia.StopHoldMusicAsync(_stopHoldMusicOptions) + callMedia => callMedia.HoldAsync(_holdOptions) + }, + new Func>?[] + { + callMedia => callMedia.HoldAsync(_holdOptionsNoMusic) + }, + new Func>?[] + { + callMedia => callMedia.UnholdAsync(_unholdOptions) } }; } + [Obsolete] private static IEnumerable TestData_HoldOperations() { return new[] @@ -807,7 +835,15 @@ public void HoldMusicOperations_Return200Ok(Func operation) }, new Func?[] { - callMedia => callMedia.StopHoldMusic(_stopHoldMusicOptions) + callMedia => callMedia.Hold(_holdOptions) + }, + new Func?[] + { + callMedia => callMedia.Hold(_holdOptionsNoMusic) + }, + new Func?[] + { + callMedia => callMedia.Unhold(_unholdOptions) } }; } diff --git a/sdk/communication/Azure.Communication.CallAutomation/tests/Events/CallAutomationEventParserTests.cs b/sdk/communication/Azure.Communication.CallAutomation/tests/Events/CallAutomationEventParserTests.cs index bdb43a38ea64..fff80c72e445 100644 --- a/sdk/communication/Azure.Communication.CallAutomation/tests/Events/CallAutomationEventParserTests.cs +++ b/sdk/communication/Azure.Communication.CallAutomation/tests/Events/CallAutomationEventParserTests.cs @@ -364,8 +364,8 @@ public void ParticipantsUpdatedEventParsed_Test() var callConnectionId = "callConnectionId"; var serverCallId = "serverCallId"; var correlationId = "correlationId"; - var participant1 = new CallParticipant(new CommunicationUserIdentifier("8:acs:12345"), false); - var participant2 = new CallParticipant(new PhoneNumberIdentifier("+123456789"), false); + var participant1 = new CallParticipant(new CommunicationUserIdentifier("8:acs:12345"), false, false); + var participant2 = new CallParticipant(new PhoneNumberIdentifier("+123456789"), false, true); var participants = new CallParticipant[] { participant1, participant2 }; var @event = CallAutomationModelFactory.ParticipantsUpdated(callConnectionId, serverCallId, correlationId, participants); JsonSerializerOptions jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; @@ -385,8 +385,10 @@ public void ParticipantsUpdatedEventParsed_Test() Assert.AreEqual(2, participantsUpdated.Participants.Count); Assert.AreEqual("8:acs:12345", participantsUpdated.Participants[0].Identifier.RawId); Assert.IsFalse(participantsUpdated.Participants[0].IsMuted); + Assert.IsFalse(participantsUpdated.Participants[0].IsOnHold); Assert.IsTrue(participantsUpdated.Participants[1].Identifier.RawId.EndsWith("123456789")); Assert.IsFalse(participantsUpdated.Participants[1].IsMuted); + Assert.IsTrue(participantsUpdated.Participants[1].IsOnHold); } else { @@ -1111,5 +1113,31 @@ public void TranscriptionFailedEventParsed_Test() Assert.Fail("Event parsed wrongfully"); } } + + [Test] + public void HoldFailedEventParsed_Test() + { + HoldFailed @event = CallAutomationModelFactory.HoldFailed( + callConnectionId: "callConnectionId", + serverCallId: "serverCallId", + correlationId: "correlationId", + operationContext: "operationContext", + resultInformation: new ResultInformation(code: 400, subCode: 8536, message: "Action failed, file could not be downloaded.")); + JsonSerializerOptions jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; + string jsonEvent = JsonSerializer.Serialize(@event, jsonOptions); + var parsedEvent = CallAutomationEventParser.Parse(jsonEvent, "Microsoft.Communication.HoldFailed"); + if (parsedEvent is HoldFailed holdFailed) + { + Assert.AreEqual("correlationId", holdFailed.CorrelationId); + Assert.AreEqual("serverCallId", holdFailed.ServerCallId); + Assert.AreEqual(400, holdFailed.ResultInformation?.Code); + Assert.AreEqual(MediaEventReasonCode.PlayDownloadFailed, holdFailed.ReasonCode); + Assert.AreEqual(8536, holdFailed.ReasonCode.GetReasonCodeValue()); + } + else + { + Assert.Fail("Event parsed wrongfully"); + } + } } }