diff --git a/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios.sln
new file mode 100644
index 00000000..369cd2e4
--- /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
+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..5e6846d5
--- /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/Helper.cs b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Helper.cs
new file mode 100644
index 00000000..5df0f999
--- /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
new file mode 100644
index 00000000..2e59205e
--- /dev/null
+++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/Program.cs
@@ -0,0 +1,730 @@
+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 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();
+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 cognitiveServicesEndpoint = builder.Configuration.GetValue("CognitiveServiceEndpoint");
+ArgumentNullException.ThrowIfNullOrEmpty(cognitiveServicesEndpoint);
+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 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://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_01_22_Preview)
+{
+ //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();
+
+
+string recordingId = string.Empty;
+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,
+ 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 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) }
+
+ };
+
+ // 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 = await client.AnswerCallAsync(answerCallOptions);
+ 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;
+
+ // await Task.Delay(20000);
+
+ await AddDualPersonaUserCCaaSAgentAsync();
+
+ // await AddTeamsUserAsCCaaSAgentAsync();
+ // await MuteParticipantAsync(callConnectionId, callerId);
+ await Task.Delay(20000);
+ 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) =>
+ {
+ 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) =>
+ {
+ 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) =>
+ {
+ logger.LogInformation($"Received call event: {addParticipantSucceededEvent.GetType()}, context: {addParticipantSucceededEvent.OperationContext}");
+ });
+ 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}");
+ });
+ client.GetEventProcessor().AttachOngoingEventProcessor(
+ answerCallResult.CallConnection.CallConnectionId, async (callDisconnectedEvent) =>
+ {
+ // await PauseOrStopRecording(callConnectionMedia, logger, true, recordingId);
+ 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 (removeParticipantFailed) =>
+ {
+ logger.LogInformation($"Received remove participant failed event: {removeParticipantFailed.GetType()}, context: {removeParticipantFailed.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}");
+ });
+
+ 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,
+ [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();
+});
+
+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 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 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);
+ 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)
+{
+
+ 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())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+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 MuteParticipantAsync(string callConnectionId, string userid)
+{
+ try
+ {
+ var target = new PhoneNumberIdentifier(userid);
+ var callConnection = client.GetCallConnection(callConnectionId);
+
+ Console.WriteLine($"Attempting to mute participant ID: {userid} in call: {callConnectionId}.");
+
+ await callConnection.MuteParticipantAsync(target).ConfigureAwait(false);
+
+ Console.WriteLine($"Successfully muted participant with 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.
+ }
+}
+async Task PauseOrStopTranscription(CallMedia callMedia, ILogger logger)
+{
+ if (isTranscriptionActive)
+ {
+ await callMedia.StopTranscriptionAsync();
+ isTranscriptionActive = false;
+ logger.LogInformation("Transcription stopped.");
+ }
+
+
+}
+
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..52a75671
--- /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",
+ "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..d9c46a71
--- /dev/null
+++ b/CallAutomation_OPS_CallingScenarios/CallAutomation_OPS_CallingScenarios/appsettings.json
@@ -0,0 +1,23 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*",
+ "CognitiveServiceEndpoint": "",
+ "CallbackUriHost": "",
+ "AcsConnectionString": "",
+ "TeamsAppId": "",
+ "AcsPhoneNumber": "",
+ "TransfereePhoneNumber": "",
+ "ParticipantPhoneNumber": "",
+ "ParticipantTeamsUser": "",
+ "DualPersonaUserId": "",
+ "CCaaSAgentUserId": "",
+ "CCaaSAgentUserId1": "",
+ "TeamsUserId": "",
+ "TeamsUserPSTNNumber": "",
+ "FileSourceUri": ""
+}
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