From 4bcac9749e8068f12d266c00bf1a111451fa5bf6 Mon Sep 17 00:00:00 2001 From: "v-balajium@microsoft.co" Date: Tue, 17 Dec 2024 22:50:59 +0530 Subject: [PATCH 1/5] Sample application CallAutomation_OPS_CallingScenarios --- .../CallAutomation_OPS_CallingScenarios.sln | 22 ++ ...CallAutomation_OPS_CallingScenarios.csproj | 15 ++ .../Program.cs | 244 ++++++++++++++++++ .../Properties/launchSettings.json | 15 ++ .../appsettings.Development.json | 8 + .../appsettings.json | 18 ++ 6 files changed, 322 insertions(+) create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.Development.json create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln new file mode 100644 index 00000000..27b4fb05 --- /dev/null +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35514.174 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CallAutomation_OPS_CallingScenarios", "CallAutomation_OPS_CallingScenarios\CallAutomation_OPS_CallingScenarios.csproj", "{2655133A-A01D-4C6D-8F18-38DA587C78E2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2655133A-A01D-4C6D-8F18-38DA587C78E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2655133A-A01D-4C6D-8F18-38DA587C78E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2655133A-A01D-4C6D-8F18-38DA587C78E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2655133A-A01D-4C6D-8F18-38DA587C78E2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj new file mode 100644 index 00000000..ebe8ee13 --- /dev/null +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + + + + + + + + + diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs new file mode 100644 index 00000000..0db4b13d --- /dev/null +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs @@ -0,0 +1,244 @@ +using Azure.Communication; +using Azure.Communication.CallAutomation; +using Azure.Messaging; +using Azure.Messaging.EventGrid; +using Azure.Messaging.EventGrid.SystemEvents; +using Microsoft.AspNetCore.Mvc; +using System.ComponentModel.DataAnnotations; +using System.Runtime.Intrinsics.X86; +using System.Text.RegularExpressions; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +/* Read config values from appsettings.json*/ +var acsConnectionString = builder.Configuration.GetValue("AcsConnectionString"); +ArgumentNullException.ThrowIfNullOrEmpty(acsConnectionString); + +var callbackUriHost = builder.Configuration.GetValue("CallbackUriHost"); +ArgumentNullException.ThrowIfNullOrEmpty(callbackUriHost); + + +var teamsAppId = builder.Configuration.GetValue("TeamsAppId"); +ArgumentNullException.ThrowIfNullOrEmpty(teamsAppId); +var acsPhoneNumber = builder.Configuration.GetValue("AcsPhoneNumber"); +ArgumentNullException.ThrowIfNullOrEmpty(acsPhoneNumber); + +var dualPersonaUserId = builder.Configuration.GetValue("DualPersonaUserId"); +ArgumentNullException.ThrowIfNullOrEmpty(dualPersonaUserId); + + +var cCaaSAgentUserId = builder.Configuration.GetValue("CCaaSAgentUserId"); +ArgumentNullException.ThrowIfNullOrEmpty(cCaaSAgentUserId); + +var cCaaSAgentUserId1 = builder.Configuration.GetValue("CCaaSAgentUserId1"); +ArgumentNullException.ThrowIfNullOrEmpty(cCaaSAgentUserId1); + +var teamsUserId = builder.Configuration.GetValue("TeamsUserId"); +ArgumentNullException.ThrowIfNullOrEmpty(teamsUserId); + +var teamsUserPSTNNumber = builder.Configuration.GetValue("TeamsUserPSTNNumber"); +ArgumentNullException.ThrowIfNullOrEmpty(teamsUserPSTNNumber); + +var PMAEndpoint = new Uri("https://uswe-04.sdf.pma.teams.microsoft.com:6448"); + +MicrosoftTeamsAppIdentifier teamsAppIdentifier = new MicrosoftTeamsAppIdentifier(teamsAppId); + +// Initialize the options with the MicrosoftTeamsAppIdentifier +CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions +{ + OPSSource = teamsAppIdentifier +}; +/* Call Automation Client */ +var client = new CallAutomationClient(pmaEndpoint: PMAEndpoint, connectionString: acsConnectionString, callautomationclientoptions); + +/* Register and make CallAutomationClient accessible via dependency injection */ +builder.Services.AddSingleton(client); +var app = builder.Build(); + + +string recordingId = string.Empty; +string recordingLocation = string.Empty; + +string callConnectionId = string.Empty; + +app.MapPost("/api/incomingCall", async ( + [FromBody] EventGridEvent[] eventGridEvents, + ILogger logger) => +{ + foreach (var eventGridEvent in eventGridEvents) + { + logger.LogInformation($"Call event received:{eventGridEvent.EventType}"); + + /* Handle system events */ + if (eventGridEvent.TryGetSystemEventData(out object eventData)) + { + /* Handle the subscription validation event. */ + if (eventData is SubscriptionValidationEventData subscriptionValidationEventData) + { + var responseData = new SubscriptionValidationResponse + { + ValidationResponse = subscriptionValidationEventData.ValidationCode + }; + return Results.Ok(responseData); + } + } + + if (eventData is AcsIncomingCallEventData incomingCallEventData) + { + var callerId = incomingCallEventData.FromCommunicationIdentifier.RawId; + var callbackUri = new Uri(new Uri(callbackUriHost), $"/api/callbacks/{Guid.NewGuid()}?callerId={callerId}"); + logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + + $"Callback url: {callbackUri}"); + var callerPhonenumber = incomingCallEventData.FromCommunicationIdentifier.PhoneNumber.Value; + + var options = new AnswerCallOptions(incomingCallEventData.IncomingCallContext, callbackUri); + + AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); + var callConnectionMedia = answerCallResult.CallConnection.GetCallMedia(); + + /* Use EventProcessor to process CallConnected event */ + var answer_result = await answerCallResult.WaitForEventProcessorAsync(); + if (answer_result.IsSuccess) + { + logger.LogInformation($"CA Received call event: {answer_result.GetType()}, callConnectionID: {answer_result.SuccessResult.CallConnectionId}, " + + $"serverCallId: {answer_result.SuccessResult.ServerCallId}"); + callConnectionId = answer_result.SuccessResult.CallConnectionId; + + + // Add CCaaS agent + var ccaasAgent = new CommunicationUserIdentifier(dualPersonaUserId); + var callInvite = new CallInvite(ccaasAgent); + var addParticipantOptions = new AddParticipantOptions(callInvite); + + var addParticipantResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptions); + logger.LogInformation($"Adding CCaaS agent to the call: {addParticipantResult.Value?.InvitationId}"); + + + //// add Teams user (8:orgid) + //var teamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); + //var callInviteTeams = new CallInvite(teamsUser); + //var addParticipantOptionsTeams = new AddParticipantOptions(callInviteTeams); + //var addParticipantResultTeams = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeams); + //logger.LogInformation($"Adding Teams user to the call: {addParticipantResultTeams.Value?.InvitationId}"); + + //// add Teams user (PSTN user number) + //var targetteamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber); + //var callerPSTNNumber = new PhoneNumberIdentifier(acsPhoneNumber); + //var callInviteTeamsPSTN = new CallInvite(targetteamsUserPSTN, callerPSTNNumber); + //var addParticipantOptionsTeamsPSTN = new AddParticipantOptions(callInviteTeamsPSTN); + //var addParticipantResultTeamsPSTN = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeamsPSTN); + //logger.LogInformation($"Adding Teams user PSTN to the call: {addParticipantResultTeamsPSTN.Value?.InvitationId}"); + + //// customer is on hold + //CommunicationIdentifier target = new PhoneNumberIdentifier(callerPhonenumber); + + //HoldOptions holdOptions = new HoldOptions(target); + //await callConnectionMedia.HoldAsync(holdOptions); + //logger.LogInformation("Customer is put on hold."); + + //UnholdOptions unholdOptions = new UnholdOptions(target); + //// After the consultation, unhold the customer (PSTN user) + //await callConnectionMedia.UnholdAsync(unholdOptions); + //logger.LogInformation("PSTN customer is unheld."); + + // transfer call to Teams user (8:orgid) + //var transferTeamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); + //var transferParticipantOptionsTeams = new TransferToParticipantOptions(transferTeamsUser); + //var transferParticipantResultTeams = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeams); + //logger.LogInformation("Transferring Teams user to the call: {InvitationId}", transferParticipantResultTeams.Value); + + // transfer call to Teams user (PSTN user number) + //var transferTeamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber); + //var transferParticipantOptionsTeamsPSTN = new TransferToParticipantOptions(transferTeamsUserPSTN); + //var transferParticipantResultTeamsPSTN = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeamsPSTN); + //logger.LogInformation("Transferring Teams user PSTN to the call: {InvitationId}", transferParticipantResultTeamsPSTN.Value); + + } + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (addParticipantSucceededEvent) => + { + logger.LogInformation($"Received call event: {addParticipantSucceededEvent.GetType()}, context: {addParticipantSucceededEvent.OperationContext}"); + }); + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (participantsUpdatedEvent) => + { + logger.LogInformation($"Received call event: {participantsUpdatedEvent.GetType()}, participants: {participantsUpdatedEvent.Participants.Count()}, sequenceId: {participantsUpdatedEvent.SequenceNumber}"); + }); + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (callDisconnectedEvent) => + { + logger.LogInformation($"Received call event: {callDisconnectedEvent.GetType()}"); + }); + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (addParticipantFailedEvent) => + { + logger.LogInformation($"Received call event: {addParticipantFailedEvent.GetType()}, CorrelationId: {addParticipantFailedEvent.CorrelationId}, " + + $"subCode: {addParticipantFailedEvent.ResultInformation?.SubCode}, message: {addParticipantFailedEvent.ResultInformation?.Message}, context: {addParticipantFailedEvent.OperationContext}"); + }); + + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (holdFailed) => + { + callConnectionId = holdFailed.CallConnectionId; + logger.LogInformation($"Received event: {holdFailed.GetType()}, CorrelationId: {holdFailed.CorrelationId}, " + + $"SubCode: {holdFailed?.ResultInformation?.SubCode}, Message: {holdFailed?.ResultInformation?.Message}"); + }); + + } + } + return Results.Ok(); +}); + +// api to handle call back events +app.MapPost("/api/callbacks/{contextId}", async ( + [FromBody] CloudEvent[] cloudEvents, + [FromRoute] string contextId, + [Required] string callerId, + CallAutomationClient callAutomationClient, + ILogger logger) => +{ + var eventProcessor = client.GetEventProcessor(); + eventProcessor.ProcessEvents(cloudEvents); + return Results.Ok(); +}); + +app.MapPost("/api/recordingFileStatus", (EventGridEvent[] eventGridEvents, ILogger logger) => +{ + foreach (var eventGridEvent in eventGridEvents) + { + if (eventGridEvent.TryGetSystemEventData(out object eventData)) + { + if (eventData is SubscriptionValidationEventData subscriptionValidationEventData) + { + var responseData = new SubscriptionValidationResponse + { + ValidationResponse = subscriptionValidationEventData.ValidationCode + }; + return Results.Ok(responseData); + } + if (eventData is AcsRecordingFileStatusUpdatedEventData statusUpdated) + { + recordingLocation = statusUpdated.RecordingStorageInfo.RecordingChunks[0].ContentLocation; + logger.LogInformation($"The recording location is : {recordingLocation}"); + } + } + } + return Results.Ok(); +}); + +app.MapGet("/download", (ILogger logger) => +{ + client.GetCallRecording().DownloadTo(new Uri(recordingLocation), "testfile.wav"); + return Results.Ok(); +}); + + +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.Run(); \ No newline at end of file diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json new file mode 100644 index 00000000..04421484 --- /dev/null +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "CallAutomation_OPS_CallingScenarios": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:8080;http://localhost:5001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.Development.json b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json new file mode 100644 index 00000000..c21c34a9 --- /dev/null +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json @@ -0,0 +1,18 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "CallbackUriHost": "", + "AcsConnectionString": "", + "TeamsAppId": "", + "AcsPhoneNumber": "", + "DualPersonaUserId": "", + "CCaaSAgentUserId": "", + "CCaaSAgentUserId1": "", + "TeamsUserId": "", + "TeamsUserPSTNNumber": "" +} From 4046c867876170ee9b49be390eef257b8d0d44af Mon Sep 17 00:00:00 2001 From: "v-balajium@microsoft.co" Date: Tue, 7 Jan 2025 13:06:31 +0530 Subject: [PATCH 2/5] ops testing changes --- .../CallAutomation_OPS_CallingScenarios.sln | 2 +- ...CallAutomation_OPS_CallingScenarios.csproj | 2 +- .../Helper.cs | 80 ++++ .../Program.cs | 402 ++++++++++++++++-- .../Properties/launchSettings.json | 2 +- .../testfile.wav | 0 6 files changed, 460 insertions(+), 28 deletions(-) create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs create mode 100644 CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/testfile.wav diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln index 27b4fb05..369cd2e4 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.12.35514.174 d17.12 +VisualStudioVersion = 17.12.35514.174 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CallAutomation_OPS_CallingScenarios", "CallAutomation_OPS_CallingScenarios\CallAutomation_OPS_CallingScenarios.csproj", "{2655133A-A01D-4C6D-8F18-38DA587C78E2}" EndProject diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj index ebe8ee13..dc4d0775 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj @@ -7,7 +7,7 @@ - + diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs new file mode 100644 index 00000000..b6f46a5a --- /dev/null +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs @@ -0,0 +1,80 @@ +using Azure.Communication.CallAutomation; +using System.Net.WebSockets; +using System.Text; + +namespace CallAutomation_OPS_CallingScenarios +{ + public class Helper + { + /// + /// Accept WebSocket Connection, and then Loop in receiving data transmitted from client. + /// + /// + public static async Task ProcessRequest(WebSocket webSocket) + { + try + { + var buffer = new byte[1024 * 4]; + var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)).Token; + WebSocketReceiveResult receiveResult = await webSocket.ReceiveAsync(new ArraySegment(buffer), cancellationToken); + + while (!receiveResult.CloseStatus.HasValue) + { + string msg = Encoding.UTF8.GetString(buffer, 0, receiveResult.Count); + + var response = StreamingDataParser.Parse(msg); + + if (response != null) + { + if (response is TranscriptionMetadata transcriptionMetadata) + { + Console.WriteLine("***************************************************************************************"); + Console.WriteLine("TRANSCRIPTION SUBSCRIPTION ID-->" + transcriptionMetadata.TranscriptionSubscriptionId); + Console.WriteLine("LOCALE-->" + transcriptionMetadata.Locale); + Console.WriteLine("CALL CONNECTION ID--?" + transcriptionMetadata.CallConnectionId); + Console.WriteLine("CORRELATION ID-->" + transcriptionMetadata.CorrelationId); + Console.WriteLine("***************************************************************************************"); + } + if (response is TranscriptionData transcriptionData) + { + Console.WriteLine("***************************************************************************************"); + Console.WriteLine("TEXT-->" + transcriptionData.Text); + Console.WriteLine("FORMAT-->" + transcriptionData.Format); + Console.WriteLine("OFFSET-->" + transcriptionData.Offset.Ticks); + Console.WriteLine("DURATION-->" + transcriptionData.Duration.Ticks); + Console.WriteLine("PARTICIPANT-->" + transcriptionData.Participant.RawId); + Console.WriteLine("CONFIDENCE-->" + transcriptionData.Confidence); + Console.WriteLine("RESULT STATUS-->" + transcriptionData.ResultState); + foreach (var word in transcriptionData.Words) + { + Console.WriteLine("WORDS TEXT-->" + word.Text); + Console.WriteLine("WORDS OFFSET-->" + word.Offset.Ticks); + Console.WriteLine("WORDS DURATION-->" + word.Duration.Ticks); + } + Console.WriteLine("***************************************************************************************"); + } + + } + + await webSocket.SendAsync( + new ArraySegment(buffer, 0, receiveResult.Count), + receiveResult.MessageType, + receiveResult.EndOfMessage, + CancellationToken.None); + + receiveResult = await webSocket.ReceiveAsync( + new ArraySegment(buffer), CancellationToken.None); + } + + await webSocket.CloseAsync(receiveResult.CloseStatus.Value, receiveResult.CloseStatusDescription, CancellationToken.None); + } + catch (Exception ex) + { + Console.WriteLine($"Exception -> {ex}"); + } + finally + { + } + } + } +} diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs index 0db4b13d..8175b282 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs @@ -1,8 +1,10 @@ +using Azure; using Azure.Communication; using Azure.Communication.CallAutomation; using Azure.Messaging; using Azure.Messaging.EventGrid; using Azure.Messaging.EventGrid.SystemEvents; +using CallAutomation_OPS_CallingScenarios; using Microsoft.AspNetCore.Mvc; using System.ComponentModel.DataAnnotations; using System.Runtime.Intrinsics.X86; @@ -19,7 +21,8 @@ var callbackUriHost = builder.Configuration.GetValue("CallbackUriHost"); ArgumentNullException.ThrowIfNullOrEmpty(callbackUriHost); - +var cognitiveServicesEndpoint = builder.Configuration.GetValue("CognitiveServiceEndpoint"); +ArgumentNullException.ThrowIfNullOrEmpty(cognitiveServicesEndpoint); var teamsAppId = builder.Configuration.GetValue("TeamsAppId"); ArgumentNullException.ThrowIfNullOrEmpty(teamsAppId); var acsPhoneNumber = builder.Configuration.GetValue("AcsPhoneNumber"); @@ -41,18 +44,24 @@ var teamsUserPSTNNumber = builder.Configuration.GetValue("TeamsUserPSTNNumber"); ArgumentNullException.ThrowIfNullOrEmpty(teamsUserPSTNNumber); +var fileSourceUri = builder.Configuration.GetValue("FileSourceUri"); +ArgumentNullException.ThrowIfNullOrEmpty(fileSourceUri); + var PMAEndpoint = new Uri("https://uswe-04.sdf.pma.teams.microsoft.com:6448"); MicrosoftTeamsAppIdentifier teamsAppIdentifier = new MicrosoftTeamsAppIdentifier(teamsAppId); +//// Initialize the options with the MicrosoftTeamsAppIdentifier // Initialize the options with the MicrosoftTeamsAppIdentifier -CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions +CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions(CallAutomationClientOptions.ServiceVersion.V2024_09_01_Preview) { - OPSSource = teamsAppIdentifier + //OPSSource = teamsAppIdentifier + + }; /* Call Automation Client */ var client = new CallAutomationClient(pmaEndpoint: PMAEndpoint, connectionString: acsConnectionString, callautomationclientoptions); - +bool isTranscriptionActive = false; /* Register and make CallAutomationClient accessible via dependency injection */ builder.Services.AddSingleton(client); var app = builder.Build(); @@ -91,12 +100,28 @@ var callbackUri = new Uri(new Uri(callbackUriHost), $"/api/callbacks/{Guid.NewGuid()}?callerId={callerId}"); logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + $"Callback url: {callbackUri}"); - var callerPhonenumber = incomingCallEventData.FromCommunicationIdentifier.PhoneNumber.Value; - var options = new AnswerCallOptions(incomingCallEventData.IncomingCallContext, callbackUri); - - AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); + //var websocketUri = callbackUriHost.Replace("https", "wss") + "ws"; + //logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + + // $"Callback url: {callbackUri}, websocket Url: {websocketUri}"); + + //TranscriptionOptions transcriptionOptions = new TranscriptionOptions(new Uri(websocketUri), + // "en-US", false, TranscriptionTransport.Websocket); + //var callerPhonenumber = incomingCallEventData.FromCommunicationIdentifier.PhoneNumber.Value; + + var answerCallOptions = new AnswerCallOptions(incomingCallEventData.IncomingCallContext, callbackUri); + //{ + // CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServicesEndpoint) }, + // TranscriptionOptions = transcriptionOptions + //}; + // Adding Custom SIP Headers (User-to-User and X-Headers) + // answerCallOptions.CustomCallingContext.AddSipUui("OBOuuivalue"); // User-to-User header + // answerCallOptions.CustomCallingContext.AddSipX("X-CustomHeader1", "HeaderValue1"); // X-header + + + AnswerCallResult answerCallResult = await client.AnswerCallAsync(answerCallOptions); var callConnectionMedia = answerCallResult.CallConnection.GetCallMedia(); + /* Use EventProcessor to process CallConnected event */ var answer_result = await answerCallResult.WaitForEventProcessorAsync(); @@ -106,22 +131,140 @@ $"serverCallId: {answer_result.SuccessResult.ServerCallId}"); callConnectionId = answer_result.SuccessResult.CallConnectionId; - - // Add CCaaS agent - var ccaasAgent = new CommunicationUserIdentifier(dualPersonaUserId); + + + //var ccaasAgent = new MicrosoftTeamsUserIdentifier(dualPersonaUserId); // teams user + var ccaasAgent = new CommunicationUserIdentifier(dualPersonaUserId); // dual persona user var callInvite = new CallInvite(ccaasAgent); var addParticipantOptions = new AddParticipantOptions(callInvite); - var addParticipantResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptions); + var addParticipantResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptions).ConfigureAwait(false); logger.LogInformation($"Adding CCaaS agent to the call: {addParticipantResult.Value?.InvitationId}"); - //// add Teams user (8:orgid) + + ////// CCaaS agent can perform mute/unmute of the PSTN participant + //await Task.Delay(20000); + //////await MuteParticipantAsync(callConnectionId, callerId); + //CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); + //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target).ConfigureAwait(false); + //// await answerCallResult.CallConnection.MuteParticipantAsync(target).ConfigureAwait(false); + + + // Define the PSTN participant to be added + //var pstnPhoneNumber = new PhoneNumberIdentifier("+918328652016"); // Replace with the PSTN number + //var callerPhoneNumber = new PhoneNumberIdentifier(acsPhoneNumber); // Your ACS Phone Number + + //// Create a CallInvite using the PSTN participant + //var callInvite = new CallInvite(pstnPhoneNumber, callerPhoneNumber); // Caller is optional + + //// Configure AddParticipant options + //var addParticipantsOptions = new AddParticipantOptions(callInvite) + //{ + // OperationContext = "AddPSTNUserOperation" // Optional context for tracking + //}; + + //// Add PSTN participant to the call + //var addParticipantsResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantsOptions); + + + + // await PauseOrStopRecording(callConnectionMedia, logger, true, recordingId); + + //// Retrieve the list of participants + //var response = await answerCallResult.CallConnection.GetParticipantsAsync(); + //var participants = response.Value; // Extract the list of participants + + //// Iterate over the list and log details + //foreach (var participant in participants) + //{ + // var participantId = participant.Identifier.RawId; // Or PhoneNumber if applicable + // logger.LogInformation($"Participant ID: {participantId}, IsMuted: {participant.IsMuted}"); + //} + //// Add CCaaS agent + + await Task.Delay(20000); + ////// add Teams user (8:orgid) //var teamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); //var callInviteTeams = new CallInvite(teamsUser); //var addParticipantOptionsTeams = new AddParticipantOptions(callInviteTeams); - //var addParticipantResultTeams = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeams); + //var addParticipantResultTeams = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeams).ConfigureAwait(false); //logger.LogInformation($"Adding Teams user to the call: {addParticipantResultTeams.Value?.InvitationId}"); + //await Task.Delay(20000); + + //CallLocator callLocator = new ServerCallLocator(callConnectionId); + //var recordingOptions = new StartRecordingOptions(callLocator) + //{ + // RecordingContent = RecordingContent.Audio, // Adjust based on content type + // RecordingFormat = RecordingFormat.Mp3, // Supported format + // RecordingChannel = RecordingChannel.Mixed, // Mixed or unmixed + // RecordingStateCallbackUri = callbackUri, + // PauseOnStart = false + //}; + //var recordingResult = await client.GetCallRecording().StartAsync(recordingOptions); + //recordingId = recordingResult.Value.RecordingId; + //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); + + //await Task.Delay(20000); + + //await PauseOrStopRecording(callConnectionMedia, logger, true, recordingId); + + //// CCaaS agent can perform mute/unmute of the PSTN participant + // await Task.Delay(20000); + ////await MuteParticipantAsync(callConnectionId, callerId); + //CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); + //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target).ConfigureAwait(false); + // await answerCallResult.CallConnection.MuteParticipantAsync(target).ConfigureAwait(false); + + + // CommunicationIdentifier target1 = new MicrosoftTeamsUserIdentifier(teamsUserId); + + // HoldOptions holdOptions = new HoldOptions(target1); + + //var res= await callConnectionMedia.HoldAsync(holdOptions).ConfigureAwait(false); + // logger.LogInformation($"Teams user is put on hold.{res.Content.ToString()}"); + + + + // UnholdOptions unholdOptions = new UnholdOptions(target1); + + // await callConnectionMedia.UnholdAsync(unholdOptions).ConfigureAwait(false); + + + //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target1).ConfigureAwait(false); + + //await Task.Delay(20000); + + //await client.GetCallConnection(callConnectionId).UnmuteParticipantAsync(target1).ConfigureAwait(false); + + //await Task.Delay(20000); + //CommunicationIdentifier target = new MicrosoftTeamsUserIdentifier("abd436ba-3128-4c3b-9c5a-b020cae8304e"); + //await answerCallResult.CallConnection.RemoveParticipantAsync(target).ConfigureAwait(false); + + //await Task.Delay(20000); + + //// customer is on hold + // CommunicationIdentifier target = new PhoneNumberIdentifier(teamsUserId); + //CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); + // Play greeting message + //var greetingPlaySource = new TextSource("HoldOperation") + //{ + // VoiceName = "en-US-NancyNeural" + //}; + // FileSource fileSource = new FileSource(new Uri(fileSourceUri)); + // HoldOptions holdOptions = new HoldOptions(target); + + // await callConnectionMedia.HoldAsync(holdOptions); + //logger.LogInformation("Customer is put on hold."); + //await Task.Delay(10000); + //UnholdOptions unholdOptions = new UnholdOptions(target); + //////// After the consultation, unhold the customer (PSTN user) + //await callConnectionMedia.UnholdAsync(unholdOptions); + //logger.LogInformation("PSTN customer is unheld."); + // await Task.Delay(10000); + + // await client.GetCallConnection(callConnectionId).UnmuteParticipantAsync(target).ConfigureAwait(false); + // await client.GetCallConnection(callConnectionId).HangUpAsync(forEveryone: false).ConfigureAwait(false); //// add Teams user (PSTN user number) //var targetteamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber); @@ -131,31 +274,106 @@ //var addParticipantResultTeamsPSTN = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeamsPSTN); //logger.LogInformation($"Adding Teams user PSTN to the call: {addParticipantResultTeamsPSTN.Value?.InvitationId}"); + + //await Task.Delay(20000); + + ///* Start the Transcription */ + //await InitiateTranscription(callConnectionMedia); + //logger.LogInformation("Transcription initiated."); + + + //await Task.Delay(20000); + //await PauseOrStopTranscription(callConnectionMedia, logger); + + //await Task.Delay(20000); + //await ResumeTranscription(callConnectionMedia, logger); + + //await Task.Delay(20000); + //await PauseOrStopTranscription(callConnectionMedia, logger); + + + + //await answerCallResult.CallConnection.MuteParticipantAsync(targetteamsUserPSTN).ConfigureAwait(false); + + //// Create the ServerCallLocator using the CallConnectionId + //var serverCallLocator = new ServerCallLocator(callConnectionId); + + //// var callLocator = new ServerCallLocator(answer_result.SuccessResult.ServerCallId); + //var recordingResult = await client.GetCallRecording().StartAsync(new StartRecordingOptions(serverCallLocator)); + //var recordingId = recordingResult.Value.RecordingId; + //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); + + /////* Start the recording */ + // CallLocator callLocator = new ServerCallLocator(callConnectionId); + + //CallLocator callLocator = new ServerCallLocator(callConnectionId); + //var recordingOptions = new StartRecordingOptions(callLocator) + //{ + // RecordingContent = RecordingContent.AudioVideo, // Adjust based on content type + // RecordingFormat = RecordingFormat.Mp4, // Supported format + // RecordingChannel = RecordingChannel.Mixed, // Mixed or unmixed + // RecordingStateCallbackUri = callbackUri, + // PauseOnStart = false, + // RecordingStorage = RecordingStorage.CreateAzureBlobContainerRecordingStorage(new Uri("https://waferwirestorage.blob.core.windows.net/ga4byos")) + //}; + //var recordingResult = await client.GetCallRecording().StartAsync(recordingOptions); + //recordingId = recordingResult.Value.RecordingId; + //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); + + + // transfer call to Teams user(8:orgid) + // await Task.Delay(20000); + + //var transferTeamsUser = new MicrosoftTeamsUserIdentifier("abd436ba-3128-4c3b-9c5a-b020cae8304e"); + //var transferParticipantOptionsTeams = new TransferToParticipantOptions(transferTeamsUser) + //{ + // Transferee = new PhoneNumberIdentifier("+18332638155") + //}; + //var transferParticipantResultTeams = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeams); + //logger.LogInformation("Transferring Teams user to the call: {InvitationId}", transferParticipantResultTeams.Value); + + + //await Task.Delay(10000); //// customer is on hold - //CommunicationIdentifier target = new PhoneNumberIdentifier(callerPhonenumber); + //CommunicationIdentifier target = new MicrosoftTeamsUserIdentifier("abd436ba-3128-4c3b-9c5a-b020cae8304e"); //HoldOptions holdOptions = new HoldOptions(target); + //await callConnectionMedia.HoldAsync(holdOptions); //logger.LogInformation("Customer is put on hold."); - + //await Task.Delay(10000); //UnholdOptions unholdOptions = new UnholdOptions(target); - //// After the consultation, unhold the customer (PSTN user) + //////// After the consultation, unhold the customer (PSTN user) //await callConnectionMedia.UnholdAsync(unholdOptions); //logger.LogInformation("PSTN customer is unheld."); - // transfer call to Teams user (8:orgid) - //var transferTeamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); - //var transferParticipantOptionsTeams = new TransferToParticipantOptions(transferTeamsUser); - //var transferParticipantResultTeams = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeams); - //logger.LogInformation("Transferring Teams user to the call: {InvitationId}", transferParticipantResultTeams.Value); // transfer call to Teams user (PSTN user number) - //var transferTeamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber); - //var transferParticipantOptionsTeamsPSTN = new TransferToParticipantOptions(transferTeamsUserPSTN); + //var transferTeamsUserPSTN = new PhoneNumberIdentifier("+12066663929"); + + //var transferParticipantOptionsTeamsPSTN = new TransferToParticipantOptions(transferTeamsUserPSTN) + //{ + // Transferee = new PhoneNumberIdentifier("+18332638155") + //}; //var transferParticipantResultTeamsPSTN = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeamsPSTN); //logger.LogInformation("Transferring Teams user PSTN to the call: {InvitationId}", transferParticipantResultTeamsPSTN.Value); + //await Task.Delay(20000); + //CommunicationIdentifier target = new PhoneNumberIdentifier("+12066663929"); + //await answerCallResult.CallConnection.RemoveParticipantAsync(target).ConfigureAwait(false); + //await ResumeRecording(callConnectionMedia, logger, recordingId); } + + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (recordingStateChangedEvent) => + { + logger.LogInformation($"Recording State Changed: {recordingStateChangedEvent.GetType()}, context: {recordingStateChangedEvent.OperationContext}"); + var recordingState = recordingStateChangedEvent.State; + + // Log the recording state + logger.LogInformation($"Recording State Changed: {recordingStateChangedEvent.GetType()}, State: {recordingState}, Context: {recordingStateChangedEvent.OperationContext}"); + + }); client.GetEventProcessor().AttachOngoingEventProcessor( answerCallResult.CallConnection.CallConnectionId, async (addParticipantSucceededEvent) => { @@ -169,6 +387,7 @@ client.GetEventProcessor().AttachOngoingEventProcessor( answerCallResult.CallConnection.CallConnectionId, async (callDisconnectedEvent) => { + // await PauseOrStopRecording(callConnectionMedia, logger, true, recordingId); logger.LogInformation($"Received call event: {callDisconnectedEvent.GetType()}"); }); client.GetEventProcessor().AttachOngoingEventProcessor( @@ -186,11 +405,32 @@ $"SubCode: {holdFailed?.ResultInformation?.SubCode}, Message: {holdFailed?.ResultInformation?.Message}"); }); + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (transcriptionStarted) => + { + logger.LogInformation($"Received transcription event: {transcriptionStarted.GetType()}"); + }); + + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (transcriptionStopped) => + { + isTranscriptionActive = false; + logger.LogInformation("Received transcription event: {type}", transcriptionStopped.GetType()); + }); + + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (TranscriptionFailed) => + { + logger.LogInformation($"Received transcription event: {TranscriptionFailed.GetType()}, CorrelationId: {TranscriptionFailed.CorrelationId}, " + + $"SubCode: {TranscriptionFailed?.ResultInformation?.SubCode}, Message: {TranscriptionFailed?.ResultInformation?.Message}"); + }); + } } return Results.Ok(); }); + // api to handle call back events app.MapPost("/api/callbacks/{contextId}", async ( [FromBody] CloudEvent[] cloudEvents, @@ -234,6 +474,45 @@ return Results.Ok(); }); +app.MapPost("/pause", async (ILogger logger, [FromQuery] string recordingId) => +{ + await client.GetCallRecording().PauseAsync(recordingId); + return Results.Ok(); +}); + +app.MapPost("/resume", async (ILogger logger, [FromQuery] string recordingId) => +{ + await client.GetCallRecording().ResumeAsync(recordingId); + return Results.Ok(); +}); + +app.MapPost("/stop", async (ILogger logger, [FromQuery] string recordingId) => +{ + await client.GetCallRecording().StopAsync(recordingId); + return Results.Ok(); +}); +async Task ResumeRecording(CallMedia callMedia, ILogger logger, string recordingId) +{ + + await client.GetCallRecording().ResumeAsync(recordingId); + logger.LogInformation($"Recording resumed. RecordingId: {recordingId}"); +} + +async Task PauseOrStopRecording(CallMedia callMedia, ILogger logger, bool stopRecording, string recordingId) +{ + + + if (stopRecording) + { + await client.GetCallRecording().StopAsync(recordingId); + logger.LogInformation($"Recording stopped. RecordingId: {recordingId}"); + } + else + { + await client.GetCallRecording().PauseAsync(recordingId); + logger.LogInformation($"Recording paused. RecordingId: {recordingId}"); + } +} if (app.Environment.IsDevelopment()) { @@ -241,4 +520,77 @@ app.UseSwaggerUI(); } -app.Run(); \ No newline at end of file +app.UseWebSockets(); +app.Use(async (context, next) => +{ + if (context.Request.Path == "/ws") + { + if (context.WebSockets.IsWebSocketRequest) + { + using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); + await Helper.ProcessRequest(webSocket); + } + else + { + context.Response.StatusCode = StatusCodes.Status400BadRequest; + } + } + else + { + await next(context); + } +}); + +app.Run(); + +async Task InitiateTranscription(CallMedia callConnectionMedia) +{ + StartTranscriptionOptions startTrasnscriptionOption = new StartTranscriptionOptions() + { + Locale = "en-US", + OperationContext = "StartTranscript" + }; + + await callConnectionMedia.StartTranscriptionAsync(startTrasnscriptionOption); + isTranscriptionActive = true; +} + +async Task ResumeTranscription(CallMedia callMedia, ILogger logger) +{ + await InitiateTranscription(callMedia); + logger.LogInformation("Transcription reinitiated."); + + +} + +async Task PauseOrStopTranscription(CallMedia callMedia, ILogger logger) +{ + if (isTranscriptionActive) + { + await callMedia.StopTranscriptionAsync(); + isTranscriptionActive = false; + logger.LogInformation("Transcription stopped."); + } + + +} +async Task MuteParticipantAsync(string callConnectionId, string userid) +{ + try + { + var target = new PhoneNumberIdentifier(userid); + var callConnection = client.GetCallConnection(callConnectionId); + + Console.WriteLine($"Attempting to mute participant with ACS ID: {userid} in call: {callConnectionId}."); + + await callConnection.MuteParticipantAsync(target).ConfigureAwait(false); + + Console.WriteLine($"Successfully muted participant with ACS ID: {userid} in call: {callConnectionId}."); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to mute participant with ACS ID: {userid}. Error: {ex.Message}"); + throw; // Re-throw the exception to allow upstream handling if needed. + } +} + diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json index 04421484..52a75671 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Properties/launchSettings.json @@ -6,7 +6,7 @@ "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "http://localhost:8080;http://localhost:5001", + "applicationUrl": "http://localhost:8080", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/testfile.wav b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/testfile.wav new file mode 100644 index 00000000..e69de29b From 373d99b94e58f90b3367268cc2f6d5d345f68867 Mon Sep 17 00:00:00 2001 From: "v-balajium@microsoft.co" Date: Tue, 21 Jan 2025 09:25:54 +0530 Subject: [PATCH 3/5] code refactor --- .../Program.cs | 541 +++++++++++------- .../appsettings.json | 23 +- 2 files changed, 333 insertions(+), 231 deletions(-) diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs index 8175b282..ae47e844 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs @@ -6,9 +6,12 @@ using Azure.Messaging.EventGrid.SystemEvents; using CallAutomation_OPS_CallingScenarios; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; using System.ComponentModel.DataAnnotations; +using System.Numerics; using System.Runtime.Intrinsics.X86; using System.Text.RegularExpressions; +using static System.Runtime.InteropServices.JavaScript.JSType; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); @@ -47,13 +50,24 @@ var fileSourceUri = builder.Configuration.GetValue("FileSourceUri"); ArgumentNullException.ThrowIfNullOrEmpty(fileSourceUri); +var participantPhoneNumber = builder.Configuration.GetValue("ParticipantPhoneNumber"); +var callerPhoneNumber = builder.Configuration.GetValue("AcsPhoneNumber"); + + +var callerTeamsUser = builder.Configuration.GetValue("TeamsUserId"); + +var participantTeamsUser = builder.Configuration.GetValue("ParticipantTeamsUser"); +var transfereePhoneNumber = builder.Configuration.GetValue("TransfereePhoneNumber"); + + + var PMAEndpoint = new Uri("https://uswe-04.sdf.pma.teams.microsoft.com:6448"); MicrosoftTeamsAppIdentifier teamsAppIdentifier = new MicrosoftTeamsAppIdentifier(teamsAppId); //// Initialize the options with the MicrosoftTeamsAppIdentifier // Initialize the options with the MicrosoftTeamsAppIdentifier -CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions(CallAutomationClientOptions.ServiceVersion.V2024_09_01_Preview) +CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions(CallAutomationClientOptions.ServiceVersion.V2023_10_03_Preview) { //OPSSource = teamsAppIdentifier @@ -71,6 +85,8 @@ string recordingLocation = string.Empty; string callConnectionId = string.Empty; +AnswerCallResult answerCallResult; +ILogger _logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger(); app.MapPost("/api/incomingCall", async ( [FromBody] EventGridEvent[] eventGridEvents, @@ -101,25 +117,26 @@ logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + $"Callback url: {callbackUri}"); - //var websocketUri = callbackUriHost.Replace("https", "wss") + "ws"; - //logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + - // $"Callback url: {callbackUri}, websocket Url: {websocketUri}"); + var websocketUri = callbackUriHost.Replace("https", "wss") + "ws"; + logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + + $"Callback url: {callbackUri}, websocket Url: {websocketUri}"); + + TranscriptionOptions transcriptionOptions = new TranscriptionOptions(new Uri(websocketUri), + "en-US", false, TranscriptionTransport.Websocket); + // var callerPhonenumber = incomingCallEventData.FromCommunicationIdentifier.PhoneNumber.Value; - //TranscriptionOptions transcriptionOptions = new TranscriptionOptions(new Uri(websocketUri), - // "en-US", false, TranscriptionTransport.Websocket); - //var callerPhonenumber = incomingCallEventData.FromCommunicationIdentifier.PhoneNumber.Value; + var answerCallOptions = new AnswerCallOptions(incomingCallEventData.IncomingCallContext, callbackUri) + { + CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServicesEndpoint) } + + }; - var answerCallOptions = new AnswerCallOptions(incomingCallEventData.IncomingCallContext, callbackUri); - //{ - // CallIntelligenceOptions = new CallIntelligenceOptions() { CognitiveServicesEndpoint = new Uri(cognitiveServicesEndpoint) }, - // TranscriptionOptions = transcriptionOptions - //}; // Adding Custom SIP Headers (User-to-User and X-Headers) - // answerCallOptions.CustomCallingContext.AddSipUui("OBOuuivalue"); // User-to-User header - // answerCallOptions.CustomCallingContext.AddSipX("X-CustomHeader1", "HeaderValue1"); // X-header + answerCallOptions.CustomCallingContext.AddSipUui("OBOuuivalue"); // User-to-User header + answerCallOptions.CustomCallingContext.AddSipX("X-CustomHeader1", "HeaderValue1"); // X-header - - AnswerCallResult answerCallResult = await client.AnswerCallAsync(answerCallOptions); + + answerCallResult = await client.AnswerCallAsync(answerCallOptions); var callConnectionMedia = answerCallResult.CallConnection.GetCallMedia(); @@ -131,152 +148,83 @@ $"serverCallId: {answer_result.SuccessResult.ServerCallId}"); callConnectionId = answer_result.SuccessResult.CallConnectionId; - - - //var ccaasAgent = new MicrosoftTeamsUserIdentifier(dualPersonaUserId); // teams user - var ccaasAgent = new CommunicationUserIdentifier(dualPersonaUserId); // dual persona user - var callInvite = new CallInvite(ccaasAgent); - var addParticipantOptions = new AddParticipantOptions(callInvite); - - var addParticipantResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptions).ConfigureAwait(false); - logger.LogInformation($"Adding CCaaS agent to the call: {addParticipantResult.Value?.InvitationId}"); - - - - ////// CCaaS agent can perform mute/unmute of the PSTN participant - //await Task.Delay(20000); - //////await MuteParticipantAsync(callConnectionId, callerId); - //CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); - //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target).ConfigureAwait(false); - //// await answerCallResult.CallConnection.MuteParticipantAsync(target).ConfigureAwait(false); - - - // Define the PSTN participant to be added - //var pstnPhoneNumber = new PhoneNumberIdentifier("+918328652016"); // Replace with the PSTN number - //var callerPhoneNumber = new PhoneNumberIdentifier(acsPhoneNumber); // Your ACS Phone Number - - //// Create a CallInvite using the PSTN participant - //var callInvite = new CallInvite(pstnPhoneNumber, callerPhoneNumber); // Caller is optional - - //// Configure AddParticipant options - //var addParticipantsOptions = new AddParticipantOptions(callInvite) - //{ - // OperationContext = "AddPSTNUserOperation" // Optional context for tracking - //}; - - //// Add PSTN participant to the call - //var addParticipantsResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantsOptions); - - - - // await PauseOrStopRecording(callConnectionMedia, logger, true, recordingId); - - //// Retrieve the list of participants - //var response = await answerCallResult.CallConnection.GetParticipantsAsync(); - //var participants = response.Value; // Extract the list of participants - - //// Iterate over the list and log details - //foreach (var participant in participants) - //{ - // var participantId = participant.Identifier.RawId; // Or PhoneNumber if applicable - // logger.LogInformation($"Participant ID: {participantId}, IsMuted: {participant.IsMuted}"); - //} - //// Add CCaaS agent - await Task.Delay(20000); - ////// add Teams user (8:orgid) - //var teamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); - //var callInviteTeams = new CallInvite(teamsUser); - //var addParticipantOptionsTeams = new AddParticipantOptions(callInviteTeams); - //var addParticipantResultTeams = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeams).ConfigureAwait(false); - //logger.LogInformation($"Adding Teams user to the call: {addParticipantResultTeams.Value?.InvitationId}"); - //await Task.Delay(20000); - - //CallLocator callLocator = new ServerCallLocator(callConnectionId); - //var recordingOptions = new StartRecordingOptions(callLocator) - //{ - // RecordingContent = RecordingContent.Audio, // Adjust based on content type - // RecordingFormat = RecordingFormat.Mp3, // Supported format - // RecordingChannel = RecordingChannel.Mixed, // Mixed or unmixed - // RecordingStateCallbackUri = callbackUri, - // PauseOnStart = false - //}; - //var recordingResult = await client.GetCallRecording().StartAsync(recordingOptions); - //recordingId = recordingResult.Value.RecordingId; - //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); - - //await Task.Delay(20000); - - //await PauseOrStopRecording(callConnectionMedia, logger, true, recordingId); - - //// CCaaS agent can perform mute/unmute of the PSTN participant - // await Task.Delay(20000); - ////await MuteParticipantAsync(callConnectionId, callerId); - //CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); - //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target).ConfigureAwait(false); - // await answerCallResult.CallConnection.MuteParticipantAsync(target).ConfigureAwait(false); - - - // CommunicationIdentifier target1 = new MicrosoftTeamsUserIdentifier(teamsUserId); - - // HoldOptions holdOptions = new HoldOptions(target1); - - //var res= await callConnectionMedia.HoldAsync(holdOptions).ConfigureAwait(false); - // logger.LogInformation($"Teams user is put on hold.{res.Content.ToString()}"); - - - - // UnholdOptions unholdOptions = new UnholdOptions(target1); - - // await callConnectionMedia.UnholdAsync(unholdOptions).ConfigureAwait(false); - - - //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target1).ConfigureAwait(false); + //await AddTeamsUserAsCCaaSAgentAsync(); + // await Task.Delay(50000); + // await PlayMediaAsync(true, false, false); + // await Task.Delay(50000); //await Task.Delay(20000); - //await client.GetCallConnection(callConnectionId).UnmuteParticipantAsync(target1).ConfigureAwait(false); + ///* Start the recording */ + CallLocator callLocator = new ServerCallLocator(answer_result.SuccessResult.ServerCallId); + var recordingResult = await client.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator)); + recordingId = recordingResult.Value.RecordingId; + logger.LogInformation($"Recording started. RecordingId: {recordingId}"); - //await Task.Delay(20000); - //CommunicationIdentifier target = new MicrosoftTeamsUserIdentifier("abd436ba-3128-4c3b-9c5a-b020cae8304e"); - //await answerCallResult.CallConnection.RemoveParticipantAsync(target).ConfigureAwait(false); + await Task.Delay(20000); + await PlayMediaAsync(false, false, false); //await Task.Delay(20000); + /* Start the recording */ - //// customer is on hold - // CommunicationIdentifier target = new PhoneNumberIdentifier(teamsUserId); - //CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); - // Play greeting message - //var greetingPlaySource = new TextSource("HoldOperation") - //{ - // VoiceName = "en-US-NancyNeural" - //}; - // FileSource fileSource = new FileSource(new Uri(fileSourceUri)); - // HoldOptions holdOptions = new HoldOptions(target); - - // await callConnectionMedia.HoldAsync(holdOptions); - //logger.LogInformation("Customer is put on hold."); - //await Task.Delay(10000); - //UnholdOptions unholdOptions = new UnholdOptions(target); - //////// After the consultation, unhold the customer (PSTN user) - //await callConnectionMedia.UnholdAsync(unholdOptions); - //logger.LogInformation("PSTN customer is unheld."); - // await Task.Delay(10000); - - // await client.GetCallConnection(callConnectionId).UnmuteParticipantAsync(target).ConfigureAwait(false); - // await client.GetCallConnection(callConnectionId).HangUpAsync(forEveryone: false).ConfigureAwait(false); - - //// add Teams user (PSTN user number) - //var targetteamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber); - //var callerPSTNNumber = new PhoneNumberIdentifier(acsPhoneNumber); - //var callInviteTeamsPSTN = new CallInvite(targetteamsUserPSTN, callerPSTNNumber); - //var addParticipantOptionsTeamsPSTN = new AddParticipantOptions(callInviteTeamsPSTN); - //var addParticipantResultTeamsPSTN = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeamsPSTN); - //logger.LogInformation($"Adding Teams user PSTN to the call: {addParticipantResultTeamsPSTN.Value?.InvitationId}"); + //var recordingResult = await StartCallRecordingAsync(callConnectionId, callbackUri); + //recordingId = recordingResult.Value.RecordingId; + //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); + // /* Start the Transcription */ + // await InitiateTranscription(callConnectionMedia); + // logger.LogInformation("Transcription initiated."); + + // await PauseOrStopTranscription(callConnectionMedia, logger); + + // await Task.Delay(20000); + + //await PauseOrStopRecording(callConnectionMedia, logger, false, recordingId); + + // // Add CCaaS Agent(dual persona user) + // await AddDualPersonaUserCCaaSAgentAsync(); + // //await Task.Delay(20000); + // //Add Teams User as CCaaS Agent + // await AddTeamsUserAsCCaaSAgentAsync(); + // //await Task.Delay(20000); + // //Add Teams User (8:orgid) + // await AddTeamsUserByOrgIdAsync(); + // //await Task.Delay(20000); + // // Add PSTN User(Teams User with Phone Number) + // await AddTeamsUserByOrgIdAsync(); + // //await Task.Delay(20000); + // // Add PSTN User to call + // await AddPSTNUserToCallAsync(); + // //await Task.Delay(20000); + // // Transfer call to Teams User(8:orgid) + // await TransferCallToTeamsUserOrgIdAsync(); + // //await Task.Delay(20000); + // // Transfer call to PSTN User + // await TransferCallToPSTNUserAsync(); + // //await Task.Delay(20000); + // // Add PSTN Participant + // await AddPSTNParticipantAsync(); + // //await Task.Delay(20000); + // // Play media to Teams User + // await PlayMediaAsync(false, true, false); + // //await Task.Delay(20000); + // // Play media to PSTN User + // await PlayMediaAsync(false, false, false); + // //await Task.Delay(20000); + // // Play media to all + // await PlayMediaAsync(true, false, false); + // //await Task.Delay(20000); + // // Play media to all + // await PlayMediaAsync(true, true, false); + // //await Task.Delay(20000); + // // Pause Recording + // await PauseOrStopRecording(callConnectionMedia, logger, false, recordingId); + // //await Task.Delay(20000); + // // Resume Recording + // await ResumeRecording(callConnectionMedia, logger, recordingId); //await Task.Delay(20000); - ///* Start the Transcription */ //await InitiateTranscription(callConnectionMedia); //logger.LogInformation("Transcription initiated."); @@ -291,78 +239,21 @@ //await Task.Delay(20000); //await PauseOrStopTranscription(callConnectionMedia, logger); - - - //await answerCallResult.CallConnection.MuteParticipantAsync(targetteamsUserPSTN).ConfigureAwait(false); - - //// Create the ServerCallLocator using the CallConnectionId - //var serverCallLocator = new ServerCallLocator(callConnectionId); - - //// var callLocator = new ServerCallLocator(answer_result.SuccessResult.ServerCallId); - //var recordingResult = await client.GetCallRecording().StartAsync(new StartRecordingOptions(serverCallLocator)); - //var recordingId = recordingResult.Value.RecordingId; - //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); - - /////* Start the recording */ - // CallLocator callLocator = new ServerCallLocator(callConnectionId); - - //CallLocator callLocator = new ServerCallLocator(callConnectionId); - //var recordingOptions = new StartRecordingOptions(callLocator) - //{ - // RecordingContent = RecordingContent.AudioVideo, // Adjust based on content type - // RecordingFormat = RecordingFormat.Mp4, // Supported format - // RecordingChannel = RecordingChannel.Mixed, // Mixed or unmixed - // RecordingStateCallbackUri = callbackUri, - // PauseOnStart = false, - // RecordingStorage = RecordingStorage.CreateAzureBlobContainerRecordingStorage(new Uri("https://waferwirestorage.blob.core.windows.net/ga4byos")) - //}; - //var recordingResult = await client.GetCallRecording().StartAsync(recordingOptions); - //recordingId = recordingResult.Value.RecordingId; - //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); - - - // transfer call to Teams user(8:orgid) - // await Task.Delay(20000); - - //var transferTeamsUser = new MicrosoftTeamsUserIdentifier("abd436ba-3128-4c3b-9c5a-b020cae8304e"); - //var transferParticipantOptionsTeams = new TransferToParticipantOptions(transferTeamsUser) - //{ - // Transferee = new PhoneNumberIdentifier("+18332638155") - //}; - //var transferParticipantResultTeams = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeams); - //logger.LogInformation("Transferring Teams user to the call: {InvitationId}", transferParticipantResultTeams.Value); - - - //await Task.Delay(10000); - //// customer is on hold - //CommunicationIdentifier target = new MicrosoftTeamsUserIdentifier("abd436ba-3128-4c3b-9c5a-b020cae8304e"); - - //HoldOptions holdOptions = new HoldOptions(target); - - //await callConnectionMedia.HoldAsync(holdOptions); - //logger.LogInformation("Customer is put on hold."); - //await Task.Delay(10000); - //UnholdOptions unholdOptions = new UnholdOptions(target); - //////// After the consultation, unhold the customer (PSTN user) - //await callConnectionMedia.UnholdAsync(unholdOptions); - //logger.LogInformation("PSTN customer is unheld."); - - - // transfer call to Teams user (PSTN user number) - //var transferTeamsUserPSTN = new PhoneNumberIdentifier("+12066663929"); - - //var transferParticipantOptionsTeamsPSTN = new TransferToParticipantOptions(transferTeamsUserPSTN) - //{ - // Transferee = new PhoneNumberIdentifier("+18332638155") - //}; - //var transferParticipantResultTeamsPSTN = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeamsPSTN); - //logger.LogInformation("Transferring Teams user PSTN to the call: {InvitationId}", transferParticipantResultTeamsPSTN.Value); - //await Task.Delay(20000); - //CommunicationIdentifier target = new PhoneNumberIdentifier("+12066663929"); - //await answerCallResult.CallConnection.RemoveParticipantAsync(target).ConfigureAwait(false); - //await ResumeRecording(callConnectionMedia, logger, recordingId); - } + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (playFailedEvent) => + { + logger.LogInformation($"Received call event: {playFailedEvent.GetType()}, CorrelationId: {playFailedEvent.CorrelationId}, " + + $"subCode: {playFailedEvent.ResultInformation?.SubCode}, message: {playFailedEvent.ResultInformation?.Message}, context: {playFailedEvent.OperationContext}"); + callConnectionId = playFailedEvent.CallConnectionId; + }); + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (playCanceled) => + { + logger.LogInformation($"Received event: {playCanceled.GetType()}"); + callConnectionId = playCanceled.CallConnectionId; + }); + client.GetEventProcessor().AttachOngoingEventProcessor( answerCallResult.CallConnection.CallConnectionId, async (recordingStateChangedEvent) => @@ -491,6 +382,212 @@ await client.GetCallRecording().StopAsync(recordingId); return Results.Ok(); }); + + async Task AddDualPersonaUserCCaaSAgentAsync() +{ + var ccaasAgent = new CommunicationUserIdentifier(dualPersonaUserId); // dual persona user + var callInvite = new CallInvite(ccaasAgent); + var addParticipantOptions = new AddParticipantOptions(callInvite); + + var addParticipantResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptions).ConfigureAwait(false); + _logger.LogInformation($"Adding DualPersonaUser as CCaaS agent to the call: {addParticipantResult.Value?.InvitationId}"); + +} + +async Task AddTeamsUserAsCCaaSAgentAsync() +{ + var ccaasAgent = new MicrosoftTeamsUserIdentifier(cCaaSAgentUserId); // teams user + var callInvite = new CallInvite(ccaasAgent); + var addParticipantOptions = new AddParticipantOptions(callInvite); + + var addParticipantResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptions).ConfigureAwait(false); + _logger.LogInformation($"Adding TeamsUser to the call: {addParticipantResult.Value?.InvitationId}"); + +} + + async Task AddTeamsUserByOrgIdAsync() +{ + //// add Teams user (8:orgid) + var teamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); + var callInviteTeams = new CallInvite(teamsUser); + var addParticipantOptionsTeams = new AddParticipantOptions(callInviteTeams); + var addParticipantResultTeams = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeams).ConfigureAwait(false); + _logger.LogInformation($"Adding Teams user to the call: {addParticipantResultTeams.Value?.InvitationId}"); +} + + async Task AddPSTNUserToCallAsync() +{ + // add Teams user (PSTN user number) + var targetteamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber); + var callerPSTNNumber = new PhoneNumberIdentifier(acsPhoneNumber); + var callInviteTeamsPSTN = new CallInvite(targetteamsUserPSTN, callerPSTNNumber); + var addParticipantOptionsTeamsPSTN = new AddParticipantOptions(callInviteTeamsPSTN); + var addParticipantResultTeamsPSTN = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeamsPSTN); + _logger.LogInformation($"Adding Teams user PSTN to the call: {addParticipantResultTeamsPSTN.Value?.InvitationId}"); + +} + + async Task TransferCallToTeamsUserOrgIdAsync() +{ + // transfer call to Teams user(8:orgid) + + var transferTeamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); + var transferParticipantOptionsTeams = new TransferToParticipantOptions(transferTeamsUser) + { + Transferee = new PhoneNumberIdentifier(transfereePhoneNumber) + }; + var transferParticipantResultTeams = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeams); + _logger.LogInformation("Transferring Teams user to the call: {InvitationId}", transferParticipantResultTeams.Value); + +} + + async Task TransferCallToPSTNUserAsync() +{ + // transfer call to Teams user (PSTN user number) + var transferTeamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber); + + var transferParticipantOptionsTeamsPSTN = new TransferToParticipantOptions(transferTeamsUserPSTN) + { + Transferee = new PhoneNumberIdentifier(transfereePhoneNumber) + }; + var transferParticipantResultTeamsPSTN = await answerCallResult.CallConnection.TransferCallToParticipantAsync(transferParticipantOptionsTeamsPSTN); + _logger.LogInformation("Transferring Teams user PSTN to the call: {InvitationId}", transferParticipantResultTeamsPSTN.Value); +} + + async Task AddPSTNParticipantAsync() +{ + // Create the PSTN participant identifier (replace with the actual PSTN number) + var pstnPhoneNumberIdentifier = new PhoneNumberIdentifier(participantPhoneNumber); + + // Create your ACS phone number identifier (replace with your ACS number) + var callerPhoneNumberIdentifier = new PhoneNumberIdentifier(acsPhoneNumber); + + // Create a CallInvite with the PSTN participant and ACS phone number (caller is optional) + var callInvite = new CallInvite(pstnPhoneNumberIdentifier, callerPhoneNumberIdentifier); + + // Configure AddParticipant options + var addParticipantsOptions = new AddParticipantOptions(callInvite) + { + OperationContext = "AddPSTNUserOperation" // Optional context for tracking + }; + + try + { + // Get the call connection and add the PSTN participant to the call + var addParticipantsResult = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantsOptions); + + + } + catch (Exception ex) + { + _logger.LogError($"Error adding PSTN participant: {ex.Message}"); + } +} + + +async Task PlayMediaAsync(bool isPlayToAll, bool isTeamsUser, bool isPlayMediaToCaller) +{ + CallMedia callMedia = GetCallMedia(); + + FileSource fileSource = new FileSource(new Uri(fileSourceUri)); + + TextSource textSource = new TextSource("Hi, this is text source played through play source thanks. Goodbye!.") + { + VoiceName = "en-US-NancyNeural" + }; + + SsmlSource ssmlSource = new SsmlSource("Hi, this is ssml test played through ssml source thanks. Goodbye!"); + + List playSources = new List() + { + fileSource + + }; + //textSource,ssmlSource + if (isPlayToAll) + { + PlayToAllOptions playToAllOptions = new PlayToAllOptions(playSources) + { + OperationContext = "playToAllContext" + }; + await callMedia.PlayToAllAsync(playToAllOptions); + } + else + { + CommunicationIdentifier target = GetCommunicationTargetIdentifier(isTeamsUser, isPlayMediaToCaller); + + Console.WriteLine("Target User:--> " + target); + + var playTo = new List { target }; + + PlayOptions playToOptions = new PlayOptions(playSources, playTo) + { + OperationContext = "playToContext" + }; + + if (target != null) + { + await callMedia.PlayAsync(playToOptions); + } + else + { + Console.WriteLine("TARGET IS EMPTY..."); + } + + } +} +CallMedia GetCallMedia() +{ + CallMedia callMedia = !string.IsNullOrEmpty(callConnectionId) ? + client.GetCallConnection(callConnectionId).GetCallMedia() + : throw new ArgumentNullException("Call connection id is empty"); + + return callMedia; +} +CommunicationIdentifier GetCommunicationTargetIdentifier(bool isTeamsUser, bool isPlayMediaToCaller) +{ + string teamsIdentifier = isPlayMediaToCaller ? callerTeamsUser : participantTeamsUser; + + string pstnIdentifier = isPlayMediaToCaller ? callerPhoneNumber : participantPhoneNumber; + + CommunicationIdentifier target = isTeamsUser ? new MicrosoftTeamsUserIdentifier(teamsIdentifier) : + new PhoneNumberIdentifier(pstnIdentifier); + + return target; +} + +async Task> StartCallRecordingAsync(string callConnectionId, Uri callbackUri) +{ + try + { + // Create a CallLocator to locate the call based on the call connection ID + var callLocator = new ServerCallLocator(callConnectionId); + + // Create the recording options with various configurations + var recordingOptions = new StartRecordingOptions(callLocator) + { + RecordingContent = RecordingContent.Audio, // You can adjust this to capture other contents (Audio, Video, or Both) + RecordingFormat = RecordingFormat.Mp3, // Specify the format of the recording, e.g., MP3, WAV, etc. + RecordingChannel = RecordingChannel.Mixed, // Mixed channel will include both the caller and callee's audio + RecordingStateCallbackUri = callbackUri, // Webhook URL for recording status notifications (optional) + PauseOnStart = false // Do not pause on start (you can set this to true if you want to pause initially) + }; + + // Start the recording asynchronously + var recordingResult = await client.GetCallRecording().StartAsync(recordingOptions); + + // Get the recording ID from the result and log it + var recordingId = recordingResult.Value.RecordingId; + _logger.LogInformation($"Recording started successfully. RecordingId: {recordingId}"); + return recordingResult; + } + catch (Exception ex) + { + // Handle any exceptions that may occur + _logger.LogError($"Error starting call recording: {ex.Message}"); + return null; // Return null or handle the error as needed + } +} async Task ResumeRecording(CallMedia callMedia, ILogger logger, string recordingId) { diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json index c21c34a9..d9c46a71 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json @@ -6,13 +6,18 @@ } }, "AllowedHosts": "*", - "CallbackUriHost": "", - "AcsConnectionString": "", - "TeamsAppId": "", - "AcsPhoneNumber": "", - "DualPersonaUserId": "", - "CCaaSAgentUserId": "", - "CCaaSAgentUserId1": "", - "TeamsUserId": "", - "TeamsUserPSTNNumber": "" + "CognitiveServiceEndpoint": "", + "CallbackUriHost": "", + "AcsConnectionString": "", + "TeamsAppId": "", + "AcsPhoneNumber": "", + "TransfereePhoneNumber": "", + "ParticipantPhoneNumber": "", + "ParticipantTeamsUser": "", + "DualPersonaUserId": "", + "CCaaSAgentUserId": "", + "CCaaSAgentUserId1": "", + "TeamsUserId": "", + "TeamsUserPSTNNumber": "", + "FileSourceUri": "" } From 1bd74015db6b94132438c3fffd8009a0b18d3004 Mon Sep 17 00:00:00 2001 From: "v-balajium@microsoft.co" Date: Mon, 7 Apr 2025 17:49:20 +0530 Subject: [PATCH 4/5] testing --- .../Program.cs | 65 ++++++++++++------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs index ae47e844..06348367 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs @@ -67,7 +67,7 @@ //// Initialize the options with the MicrosoftTeamsAppIdentifier // Initialize the options with the MicrosoftTeamsAppIdentifier -CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions(CallAutomationClientOptions.ServiceVersion.V2023_10_03_Preview) +CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions(CallAutomationClientOptions.ServiceVersion.V2024_09_01_Preview) { //OPSSource = teamsAppIdentifier @@ -147,9 +147,29 @@ logger.LogInformation($"CA Received call event: {answer_result.GetType()}, callConnectionID: {answer_result.SuccessResult.CallConnectionId}, " + $"serverCallId: {answer_result.SuccessResult.ServerCallId}"); callConnectionId = answer_result.SuccessResult.CallConnectionId; + + await Task.Delay(20000); + + // await AddDualPersonaUserCCaaSAgentAsync(); + + await AddTeamsUserAsCCaaSAgentAsync(); + // await MuteParticipantAsync(callConnectionId, callerId); + await Task.Delay(20000); + + await AddTeamsUserByOrgIdAsync(); await Task.Delay(20000); - //await AddTeamsUserAsCCaaSAgentAsync(); + + CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); + await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target).ConfigureAwait(false); + await answerCallResult.CallConnection.MuteParticipantAsync(target).ConfigureAwait(false); + + CommunicationIdentifier target1 = new MicrosoftTeamsUserIdentifier(teamsUserId); + await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target1).ConfigureAwait(false); + + await Task.Delay(20000); + + await client.GetCallConnection(callConnectionId).UnmuteParticipantAsync(target1).ConfigureAwait(false); // await Task.Delay(50000); // await PlayMediaAsync(true, false, false); @@ -157,13 +177,13 @@ //await Task.Delay(20000); ///* Start the recording */ - CallLocator callLocator = new ServerCallLocator(answer_result.SuccessResult.ServerCallId); - var recordingResult = await client.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator)); - recordingId = recordingResult.Value.RecordingId; - logger.LogInformation($"Recording started. RecordingId: {recordingId}"); + //CallLocator callLocator = new ServerCallLocator(answer_result.SuccessResult.ServerCallId); + //var recordingResult = await client.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator)); + //recordingId = recordingResult.Value.RecordingId; + //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); - await Task.Delay(20000); - await PlayMediaAsync(false, false, false); + //await Task.Delay(20000); + //await PlayMediaAsync(false, false, false); //await Task.Delay(20000); /* Start the recording */ @@ -184,7 +204,7 @@ //await PauseOrStopRecording(callConnectionMedia, logger, false, recordingId); // // Add CCaaS Agent(dual persona user) - // await AddDualPersonaUserCCaaSAgentAsync(); + //await AddDualPersonaUserCCaaSAgentAsync(); // //await Task.Delay(20000); // //Add Teams User as CCaaS Agent // await AddTeamsUserAsCCaaSAgentAsync(); @@ -658,18 +678,6 @@ async Task ResumeTranscription(CallMedia callMedia, ILogger logger) logger.LogInformation("Transcription reinitiated."); -} - -async Task PauseOrStopTranscription(CallMedia callMedia, ILogger logger) -{ - if (isTranscriptionActive) - { - await callMedia.StopTranscriptionAsync(); - isTranscriptionActive = false; - logger.LogInformation("Transcription stopped."); - } - - } async Task MuteParticipantAsync(string callConnectionId, string userid) { @@ -678,11 +686,11 @@ async Task MuteParticipantAsync(string callConnectionId, string userid) var target = new PhoneNumberIdentifier(userid); var callConnection = client.GetCallConnection(callConnectionId); - Console.WriteLine($"Attempting to mute participant with ACS ID: {userid} in call: {callConnectionId}."); + Console.WriteLine($"Attempting to mute participant ID: {userid} in call: {callConnectionId}."); await callConnection.MuteParticipantAsync(target).ConfigureAwait(false); - Console.WriteLine($"Successfully muted participant with ACS ID: {userid} in call: {callConnectionId}."); + Console.WriteLine($"Successfully muted participant with ID: {userid} in call: {callConnectionId}."); } catch (Exception ex) { @@ -690,4 +698,15 @@ async Task MuteParticipantAsync(string callConnectionId, string userid) throw; // Re-throw the exception to allow upstream handling if needed. } } +async Task PauseOrStopTranscription(CallMedia callMedia, ILogger logger) +{ + if (isTranscriptionActive) + { + await callMedia.StopTranscriptionAsync(); + isTranscriptionActive = false; + logger.LogInformation("Transcription stopped."); + } + + +} From af0730c5487830380a92ac877fe58f863f0716bd Mon Sep 17 00:00:00 2001 From: "v-balajium@microsoft.co" Date: Mon, 21 Apr 2025 17:11:46 +0530 Subject: [PATCH 5/5] Ops testing changes --- ...CallAutomation_OPS_CallingScenarios.csproj | 2 +- .../Helper.cs | 28 +- .../Program.cs | 262 ++++++++++-------- 3 files changed, 155 insertions(+), 137 deletions(-) diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj index dc4d0775..5e6846d5 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.csproj @@ -7,7 +7,7 @@ - + diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs index b6f46a5a..5df0f999 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs @@ -37,20 +37,20 @@ public static async Task ProcessRequest(WebSocket webSocket) } if (response is TranscriptionData transcriptionData) { - Console.WriteLine("***************************************************************************************"); - Console.WriteLine("TEXT-->" + transcriptionData.Text); - Console.WriteLine("FORMAT-->" + transcriptionData.Format); - Console.WriteLine("OFFSET-->" + transcriptionData.Offset.Ticks); - Console.WriteLine("DURATION-->" + transcriptionData.Duration.Ticks); - Console.WriteLine("PARTICIPANT-->" + transcriptionData.Participant.RawId); - Console.WriteLine("CONFIDENCE-->" + transcriptionData.Confidence); - Console.WriteLine("RESULT STATUS-->" + transcriptionData.ResultState); - foreach (var word in transcriptionData.Words) - { - Console.WriteLine("WORDS TEXT-->" + word.Text); - Console.WriteLine("WORDS OFFSET-->" + word.Offset.Ticks); - Console.WriteLine("WORDS DURATION-->" + word.Duration.Ticks); - } + //Console.WriteLine("***************************************************************************************"); + //Console.WriteLine("TEXT-->" + transcriptionData.Text); + //Console.WriteLine("FORMAT-->" + transcriptionData.Format); + //Console.WriteLine("OFFSET-->" + transcriptionData.Offset.Ticks); + //Console.WriteLine("DURATION-->" + transcriptionData.Duration.Ticks); + //Console.WriteLine("PARTICIPANT-->" + transcriptionData.Participant.RawId); + //Console.WriteLine("CONFIDENCE-->" + transcriptionData.Confidence); + //Console.WriteLine("RESULT STATUS-->" + transcriptionData.ResultState); + //foreach (var word in transcriptionData.Words) + //{ + // Console.WriteLine("WORDS TEXT-->" + word.Text); + // Console.WriteLine("WORDS OFFSET-->" + word.Offset.Ticks); + // Console.WriteLine("WORDS DURATION-->" + word.Duration.Ticks); + //} Console.WriteLine("***************************************************************************************"); } diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs index 06348367..2e59205e 100644 --- a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs +++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs @@ -61,13 +61,13 @@ -var PMAEndpoint = new Uri("https://uswe-04.sdf.pma.teams.microsoft.com:6448"); +var PMAEndpoint = new Uri("https://uswc-02.sdf.pma.teams.microsoft.com"); MicrosoftTeamsAppIdentifier teamsAppIdentifier = new MicrosoftTeamsAppIdentifier(teamsAppId); //// Initialize the options with the MicrosoftTeamsAppIdentifier // Initialize the options with the MicrosoftTeamsAppIdentifier -CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions(CallAutomationClientOptions.ServiceVersion.V2024_09_01_Preview) +CallAutomationClientOptions callautomationclientoptions = new CallAutomationClientOptions(CallAutomationClientOptions.ServiceVersion.V2024_01_22_Preview) { //OPSSource = teamsAppIdentifier @@ -117,12 +117,12 @@ logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + $"Callback url: {callbackUri}"); - var websocketUri = callbackUriHost.Replace("https", "wss") + "ws"; - logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + - $"Callback url: {callbackUri}, websocket Url: {websocketUri}"); + //var websocketUri = callbackUriHost.Replace("https", "wss") + "ws"; + //logger.LogInformation($"Incoming call - correlationId: {incomingCallEventData.CorrelationId}, " + + // $"Callback url: {callbackUri}, websocket Url: {websocketUri}"); - TranscriptionOptions transcriptionOptions = new TranscriptionOptions(new Uri(websocketUri), - "en-US", false, TranscriptionTransport.Websocket); + //TranscriptionOptions transcriptionOptions = new TranscriptionOptions(new Uri(websocketUri), + // "en-US", false, TranscriptionTransport.Websocket); // var callerPhonenumber = incomingCallEventData.FromCommunicationIdentifier.PhoneNumber.Value; var answerCallOptions = new AnswerCallOptions(incomingCallEventData.IncomingCallContext, callbackUri) @@ -132,8 +132,8 @@ }; // Adding Custom SIP Headers (User-to-User and X-Headers) - answerCallOptions.CustomCallingContext.AddSipUui("OBOuuivalue"); // User-to-User header - answerCallOptions.CustomCallingContext.AddSipX("X-CustomHeader1", "HeaderValue1"); // X-header + //answerCallOptions.CustomCallingContext.AddSipUui("OBOuuivalue"); // User-to-User header + //answerCallOptions.CustomCallingContext.AddSipX("X-CustomHeader1", "HeaderValue1"); // X-header answerCallResult = await client.AnswerCallAsync(answerCallOptions); @@ -148,118 +148,120 @@ $"serverCallId: {answer_result.SuccessResult.ServerCallId}"); callConnectionId = answer_result.SuccessResult.CallConnectionId; - await Task.Delay(20000); + // await Task.Delay(20000); - // await AddDualPersonaUserCCaaSAgentAsync(); + await AddDualPersonaUserCCaaSAgentAsync(); - await AddTeamsUserAsCCaaSAgentAsync(); + // await AddTeamsUserAsCCaaSAgentAsync(); // await MuteParticipantAsync(callConnectionId, callerId); await Task.Delay(20000); - - await AddTeamsUserByOrgIdAsync(); - - await Task.Delay(20000); - - CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); - await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target).ConfigureAwait(false); - await answerCallResult.CallConnection.MuteParticipantAsync(target).ConfigureAwait(false); - - CommunicationIdentifier target1 = new MicrosoftTeamsUserIdentifier(teamsUserId); - await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target1).ConfigureAwait(false); - - await Task.Delay(20000); - - await client.GetCallConnection(callConnectionId).UnmuteParticipantAsync(target1).ConfigureAwait(false); - - // await Task.Delay(50000); - // await PlayMediaAsync(true, false, false); - // await Task.Delay(50000); - //await Task.Delay(20000); - - ///* Start the recording */ - //CallLocator callLocator = new ServerCallLocator(answer_result.SuccessResult.ServerCallId); - //var recordingResult = await client.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator)); - //recordingId = recordingResult.Value.RecordingId; - //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); - - //await Task.Delay(20000); - //await PlayMediaAsync(false, false, false); - - //await Task.Delay(20000); - /* Start the recording */ - - //var recordingResult = await StartCallRecordingAsync(callConnectionId, callbackUri); - - //recordingId = recordingResult.Value.RecordingId; - //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); - - // /* Start the Transcription */ - // await InitiateTranscription(callConnectionMedia); - // logger.LogInformation("Transcription initiated."); - - // await PauseOrStopTranscription(callConnectionMedia, logger); - - // await Task.Delay(20000); - - //await PauseOrStopRecording(callConnectionMedia, logger, false, recordingId); - - // // Add CCaaS Agent(dual persona user) - //await AddDualPersonaUserCCaaSAgentAsync(); - // //await Task.Delay(20000); - // //Add Teams User as CCaaS Agent - // await AddTeamsUserAsCCaaSAgentAsync(); - // //await Task.Delay(20000); - // //Add Teams User (8:orgid) - // await AddTeamsUserByOrgIdAsync(); - // //await Task.Delay(20000); - // // Add PSTN User(Teams User with Phone Number) - // await AddTeamsUserByOrgIdAsync(); - // //await Task.Delay(20000); - // // Add PSTN User to call - // await AddPSTNUserToCallAsync(); - // //await Task.Delay(20000); - // // Transfer call to Teams User(8:orgid) - // await TransferCallToTeamsUserOrgIdAsync(); - // //await Task.Delay(20000); - // // Transfer call to PSTN User - // await TransferCallToPSTNUserAsync(); - // //await Task.Delay(20000); - // // Add PSTN Participant - // await AddPSTNParticipantAsync(); - // //await Task.Delay(20000); - // // Play media to Teams User - // await PlayMediaAsync(false, true, false); - // //await Task.Delay(20000); - // // Play media to PSTN User - // await PlayMediaAsync(false, false, false); - // //await Task.Delay(20000); - // // Play media to all - // await PlayMediaAsync(true, false, false); - // //await Task.Delay(20000); - // // Play media to all - // await PlayMediaAsync(true, true, false); - // //await Task.Delay(20000); - // // Pause Recording - // await PauseOrStopRecording(callConnectionMedia, logger, false, recordingId); - // //await Task.Delay(20000); - // // Resume Recording - // await ResumeRecording(callConnectionMedia, logger, recordingId); - //await Task.Delay(20000); - ///* Start the Transcription */ - //await InitiateTranscription(callConnectionMedia); - //logger.LogInformation("Transcription initiated."); - - - //await Task.Delay(20000); - //await PauseOrStopTranscription(callConnectionMedia, logger); - - //await Task.Delay(20000); - //await ResumeTranscription(callConnectionMedia, logger); - - //await Task.Delay(20000); - //await PauseOrStopTranscription(callConnectionMedia, logger); - - } + await TransferCallToTeamsUserOrgIdAsync(); + //await AddTeamsUserByOrgIdAsync(); + + await Task.Delay(20000); + + //await RemoveTeamsUserByOrgIdAsync(); + + //CommunicationIdentifier target = new PhoneNumberIdentifier("+18332638155"); + //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target).ConfigureAwait(false); + //await answerCallResult.CallConnection.MuteParticipantAsync(target).ConfigureAwait(false); + + //CommunicationIdentifier target1 = new MicrosoftTeamsUserIdentifier(teamsUserId); + //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target1).ConfigureAwait(false); + + //await Task.Delay(20000); + + //await client.GetCallConnection(callConnectionId).MuteParticipantAsync(target1).ConfigureAwait(false); + + // await Task.Delay(50000); + // await PlayMediaAsync(true, false, false); + // await Task.Delay(50000); + //await Task.Delay(20000); + + ///* Start the recording */ + //CallLocator callLocator = new ServerCallLocator(answer_result.SuccessResult.ServerCallId); + //var recordingResult = await client.GetCallRecording().StartAsync(new StartRecordingOptions(callLocator)); + //recordingId = recordingResult.Value.RecordingId; + //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); + + //await Task.Delay(20000); + //await PlayMediaAsync(false, false, false); + + //await Task.Delay(20000); + /* Start the recording */ + + //var recordingResult = await StartCallRecordingAsync(callConnectionId, callbackUri); + + //recordingId = recordingResult.Value.RecordingId; + //logger.LogInformation($"Recording started. RecordingId: {recordingId}"); + + // /* Start the Transcription */ + // await InitiateTranscription(callConnectionMedia); + // logger.LogInformation("Transcription initiated."); + + // await PauseOrStopTranscription(callConnectionMedia, logger); + + // await Task.Delay(20000); + + //await PauseOrStopRecording(callConnectionMedia, logger, false, recordingId); + + // // Add CCaaS Agent(dual persona user) + //await AddDualPersonaUserCCaaSAgentAsync(); + // //await Task.Delay(20000); + // //Add Teams User as CCaaS Agent + // await AddTeamsUserAsCCaaSAgentAsync(); + // //await Task.Delay(20000); + // //Add Teams User (8:orgid) + // await AddTeamsUserByOrgIdAsync(); + // //await Task.Delay(20000); + // // Add PSTN User(Teams User with Phone Number) + // await AddTeamsUserByOrgIdAsync(); + // //await Task.Delay(20000); + // // Add PSTN User to call + // await AddPSTNUserToCallAsync(); + // //await Task.Delay(20000); + // // Transfer call to Teams User(8:orgid) + // await TransferCallToTeamsUserOrgIdAsync(); + // //await Task.Delay(20000); + // // Transfer call to PSTN User + // await TransferCallToPSTNUserAsync(); + // //await Task.Delay(20000); + // // Add PSTN Participant + // await AddPSTNParticipantAsync(); + // //await Task.Delay(20000); + // // Play media to Teams User + // await PlayMediaAsync(false, true, false); + // //await Task.Delay(20000); + // // Play media to PSTN User + // await PlayMediaAsync(false, false, false); + // //await Task.Delay(20000); + // // Play media to all + // await PlayMediaAsync(true, false, false); + // //await Task.Delay(20000); + // // Play media to all + // await PlayMediaAsync(true, true, false); + // //await Task.Delay(20000); + // // Pause Recording + // await PauseOrStopRecording(callConnectionMedia, logger, false, recordingId); + // //await Task.Delay(20000); + // // Resume Recording + // await ResumeRecording(callConnectionMedia, logger, recordingId); + //await Task.Delay(20000); + ///* Start the Transcription */ + //await InitiateTranscription(callConnectionMedia); + //logger.LogInformation("Transcription initiated."); + + + //await Task.Delay(20000); + //await PauseOrStopTranscription(callConnectionMedia, logger); + + //await Task.Delay(20000); + //await ResumeTranscription(callConnectionMedia, logger); + + //await Task.Delay(20000); + //await PauseOrStopTranscription(callConnectionMedia, logger); + + } client.GetEventProcessor().AttachOngoingEventProcessor( answerCallResult.CallConnection.CallConnectionId, async (playFailedEvent) => { @@ -290,7 +292,12 @@ { logger.LogInformation($"Received call event: {addParticipantSucceededEvent.GetType()}, context: {addParticipantSucceededEvent.OperationContext}"); }); - client.GetEventProcessor().AttachOngoingEventProcessor( + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (removeParticipantSucceededEvent) => + { + logger.LogInformation($"Received remove participant succeeded event: {removeParticipantSucceededEvent.GetType()}, context: {removeParticipantSucceededEvent.OperationContext}"); + }); + client.GetEventProcessor().AttachOngoingEventProcessor( answerCallResult.CallConnection.CallConnectionId, async (participantsUpdatedEvent) => { logger.LogInformation($"Received call event: {participantsUpdatedEvent.GetType()}, participants: {participantsUpdatedEvent.Participants.Count()}, sequenceId: {participantsUpdatedEvent.SequenceNumber}"); @@ -307,8 +314,12 @@ logger.LogInformation($"Received call event: {addParticipantFailedEvent.GetType()}, CorrelationId: {addParticipantFailedEvent.CorrelationId}, " + $"subCode: {addParticipantFailedEvent.ResultInformation?.SubCode}, message: {addParticipantFailedEvent.ResultInformation?.Message}, context: {addParticipantFailedEvent.OperationContext}"); }); - - client.GetEventProcessor().AttachOngoingEventProcessor( + client.GetEventProcessor().AttachOngoingEventProcessor( + answerCallResult.CallConnection.CallConnectionId, async (removeParticipantFailed) => + { + logger.LogInformation($"Received remove participant failed event: {removeParticipantFailed.GetType()}, context: {removeParticipantFailed.OperationContext}"); + }); + client.GetEventProcessor().AttachOngoingEventProcessor( answerCallResult.CallConnection.CallConnectionId, async (holdFailed) => { callConnectionId = holdFailed.CallConnectionId; @@ -434,8 +445,15 @@ async Task AddTeamsUserByOrgIdAsync() var addParticipantResultTeams = await answerCallResult.CallConnection.AddParticipantAsync(addParticipantOptionsTeams).ConfigureAwait(false); _logger.LogInformation($"Adding Teams user to the call: {addParticipantResultTeams.Value?.InvitationId}"); } - - async Task AddPSTNUserToCallAsync() +async Task RemoveTeamsUserByOrgIdAsync() +{ + //// Remove Teams user (8:orgid) + var teamsUser = new MicrosoftTeamsUserIdentifier(teamsUserId); + var re = new RemoveParticipantOptions(teamsUser); + var result= await answerCallResult.CallConnection.RemoveParticipantAsync(re).ConfigureAwait(false); + _logger.LogInformation($"Removing Teams user from the call: {result.Value}"); +} +async Task AddPSTNUserToCallAsync() { // add Teams user (PSTN user number) var targetteamsUserPSTN = new PhoneNumberIdentifier(teamsUserPSTNNumber);