From 4948bb478c5a63c4da89ea4f39eddd2b469a3516 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Mon, 21 Jul 2025 22:17:44 +0530 Subject: [PATCH 01/27] Lobby Call Support Sample - Initial Checkin without client app modifications --- .../LobbyCallSupportSample.sln | 25 ++ .../LobbyCallSupportSample/Helper.cs | 100 +++++ .../InstructionToDeploy.txt | 16 + .../LobbyCallSupportSample.csproj | 20 + .../LobbyCallSupportSample/Program.cs | 385 ++++++++++++++++++ .../Properties/launchSettings.json | 41 ++ .../appsettings.Development.json | 8 + .../LobbyCallSupportSample/appsettings.json | 14 + 8 files changed, 609 insertions(+) create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample.sln create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/Program.cs create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/appsettings.Development.json create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json diff --git a/LobbyCallSupportSample/LobbyCallSupportSample.sln b/LobbyCallSupportSample/LobbyCallSupportSample.sln new file mode 100644 index 00000000..3a659249 --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35728.132 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LobbyCallSupportSample", "LobbyCallSupportSample\LobbyCallSupportSample.csproj", "{3CAA0D48-2795-C343-DA4B-6B3F56CBB314}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3CAA0D48-2795-C343-DA4B-6B3F56CBB314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CAA0D48-2795-C343-DA4B-6B3F56CBB314}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CAA0D48-2795-C343-DA4B-6B3F56CBB314}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CAA0D48-2795-C343-DA4B-6B3F56CBB314}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {99998281-4DF2-4536-B2AD-266FB84E2025} + EndGlobalSection +EndGlobal diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs new file mode 100644 index 00000000..99f1a5bc --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs @@ -0,0 +1,100 @@ +using Azure.Communication.CallAutomation; +using System.Net.WebSockets; +using System.Text; +using System.Text.Json; + +namespace LobbyCallSupportSample +{ + public static class Helper + { + 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 = StreamingData.Parse(msg); + + if (response != null) + { + if (response is AudioMetadata audioMetadata) + { + Console.WriteLine("***************************************************************************************"); + Console.WriteLine("MEDIA SUBSCRIPTION ID-->" + audioMetadata.MediaSubscriptionId); + Console.WriteLine("ENCODING-->" + audioMetadata.Encoding); + Console.WriteLine("SAMPLE RATE-->" + audioMetadata.SampleRate); + Console.WriteLine("CHANNELS-->" + audioMetadata.Channels); + //Console.WriteLine("LENGTH-->" + audioMetadata.Length); + Console.WriteLine("***************************************************************************************"); + } + if (response is AudioData audioData) + { + Console.WriteLine("***************************************************************************************"); + Console.WriteLine("DATA-->" + JsonSerializer.Serialize(audioData.Data)); + Console.WriteLine("TIMESTAMP-->" + audioData.Timestamp); + Console.WriteLine("IS SILENT-->" + audioData.IsSilent); + if (audioData.Participant != null && audioData.Participant.RawId != null) + { + Console.WriteLine("Participant Id-->" + audioData.Participant.RawId); + } + + Console.WriteLine("***************************************************************************************"); + } + + 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); + Console.WriteLine("DURATION-->" + transcriptionData.Duration); + 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); + Console.WriteLine("WORDS DURATION-->" + word.Duration); + } + 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/LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt b/LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt new file mode 100644 index 00000000..83a9af5c --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt @@ -0,0 +1,16 @@ +Install Git Bash + +Open Git Bash + +Navigate to deployment file location + +#://GA5ContosoApp/GA5ContosoApp + +Execute following command to create executable. +chmod +x azure-deploy.sh + +Execute following command to deploy +./azure-deploy.sh + +https://.scm.azurewebsites.net/swagger/index.html + diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj b/LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj new file mode 100644 index 00000000..88be9e65 --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj @@ -0,0 +1,20 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs new file mode 100644 index 00000000..087e02e1 --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -0,0 +1,385 @@ +using Azure.Communication; +using Azure.Communication.CallAutomation; +using Azure.Core; +using Azure.Messaging; +using Azure.Messaging.EventGrid; +using Azure.Messaging.EventGrid.SystemEvents; +using System.Text; + +#region Bootstrap +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); +#endregion + +#region Global Variables for LobbyCallSupportSample + +string + // Configuration variables + acsConnectionString = + builder.Configuration["acsConnectionString"] + ?? throw new ArgumentNullException("acsConnectionString"), + callbackUriHost = + builder.Configuration["callbackUriHost"] + ?? throw new ArgumentNullException("callbackUriHost"), + pmaEndpoint = + builder.Configuration["pmaEndpoint"] + ?? throw new ArgumentNullException("pmaEndpoint"), + acsGeneratedId = + builder.Configuration["acsGeneratedId"] + ?? throw new ArgumentNullException("acsGeneratedId"), + + // Track which type of workflow call was last created + lastWorkflowCallType = string.Empty, // "CallTwo" or "CallThree" + acsIdentity = string.Empty, + // Call connection IDs + targetCallConnectionId = string.Empty, + lobbyConnectionId = string.Empty, // User's incoming call + lobbyCallerId = string.Empty, // User's incoming call + callConnectionId2 = string.Empty; // ACS user's redirected call + +CallAutomationClient client = + new(pmaEndpoint: new Uri(pmaEndpoint), connectionString: acsConnectionString); +#endregion + +#region Event Handler + +app.MapPost("/api/LobbyCallSupportEventHandler", async (EventGridEvent[] eventGridEvents, ILogger logger) => +{ + StringBuilder msgLog = new(); // to make string builder thread-safe; declared here + msgLog.AppendLine(""" + + ~~~~~~~~~~~~ /api/LobbyCallSupportEventHandler ~~~~~~~~~~~~ + """); + 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 AcsIncomingCallEventData incomingCallEventData) + { + msgLog.AppendLine($"Event received: {eventGridEvent.EventType}"); + + string + fromCallerId = acsIdentity = incomingCallEventData.FromCommunicationIdentifier.RawId, + toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; + + // Lobby Call: Answer + if (toCallerId.Contains(acsGeneratedId)) + { + #region Answer Call + Uri callbackUri = new (new Uri(callbackUriHost), $"/api/callbacks"); + AnswerCallOptions options = new (incomingCallEventData.IncomingCallContext, callbackUri) + { + OperationContext = "LobbyCall", + CallIntelligenceOptions = new CallIntelligenceOptions + { + CognitiveServicesEndpoint = new Uri("https://cognitive-service-waferwire.cognitiveservices.azure.com/") + } + }; + + AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); + lobbyConnectionId = answerCallResult.CallConnection.CallConnectionId; + + msgLog.AppendLine($""" + User Call(Inbound) Answered by Call Automation. + From Caller Raw Id: {fromCallerId} + To Caller Raw Id: {toCallerId} + Lobby Call Connection Id: {lobbyConnectionId} + Correlation Id: {incomingCallEventData.CorrelationId} + Lobby Call answered successfully. + """); + #endregion + } + + else + { + //msgLog.AppendLine($"Call filtered out - not matching expected scenarios"); + } + } + } + } + var logToSend = msgLog.ToString(); // avoiding multiple logs + msgLog.Clear(); + + Console.WriteLine(logToSend); + return Results.Text(logToSend, "text/plain"); +}); + +#endregion + +#region Callback Handler + +app.MapPost("/api/callbacks", async (CloudEvent[] cloudEvents, ILogger logger) => +{ + StringBuilder msgLog = new(); // to make string builder thread-safe; declared here + + foreach (var cloudEvent in cloudEvents) + { + CallAutomationEventBase parsedEvent = CallAutomationEventParser.Parse(cloudEvent); + var callConnection = client.GetCallConnection(parsedEvent.CallConnectionId); + if (parsedEvent is CallConnected callConnected) + { + Console.WriteLine($"~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ "); + Console.WriteLine($"Received callConnected.CallConnectionId : {callConnected.CallConnectionId}"); + if ((callConnected.OperationContext??string.Empty).Equals("LobbyCall", StringComparison.Ordinal)) + { + // added logs to avoid multiple logs for the same callback + msgLog.AppendLine($""" + ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ + Received call event : {parsedEvent.GetType()} + Lobby Call Connection Id: {callConnected.CallConnectionId} + Correlation Id: {callConnected.CorrelationId} + """); + + // record lobby caller id and connection id + CallConnection lobbyCallConnection = client.GetCallConnection(callConnected.CallConnectionId); + CallConnectionProperties callConnectionProperties = lobbyCallConnection.GetCallConnectionProperties(); + lobbyCallerId = callConnectionProperties.Source.RawId; + lobbyConnectionId = callConnectionProperties.CallConnectionId; + Console.WriteLine($""" + Lobby Caller Id: {lobbyCallerId} + Lobby Connection Id: {lobbyConnectionId} + """); + + #region Play lobby waiting message + // setup cognitive service end point + CallMedia callMedia = !string.IsNullOrEmpty(callConnected.CallConnectionId) ? + client.GetCallConnection(callConnected.CallConnectionId).GetCallMedia() + : throw new ArgumentNullException("Call connection id is empty"); + TextSource textSource = + new("You are currently in a lobby call, we will notify the admin that you are waiting.") + { + VoiceName = "en-US-NancyNeural" + }; + + List playTo = + new() { new CommunicationUserIdentifier(acsIdentity) }; + + PlayOptions playToOptions = new(playSource: textSource, playTo: playTo) + { + OperationContext = "playToContext" + }; + await callMedia.PlayAsync(playToOptions); + #endregion + } + } + else if (parsedEvent is PlayCompleted playCompleted) + { + // added logs to avoid multiple logs for the same callback + msgLog.AppendLine($""" + ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ + Received event: {parsedEvent.GetType()} + """); + + // TODO: Notify Target Cal user + // By Recognition or pop up in Client app + + #region Move Participant + try + { + msgLog.AppendLine($""" + ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ + Move Participant operation started.. + Source Caller Id: {lobbyCallerId} + Source Connection Id: {lobbyConnectionId} + Target Connection Id: {targetCallConnectionId} + """); + + // Get the target connection + CallConnection targetConnection = client.GetCallConnection(targetCallConnectionId); + + // Get participants from source connection for reference + CallConnection sourceConnection = client.GetCallConnection(lobbyConnectionId); + + // Create participant identifier based on the input + CommunicationIdentifier participantToMove; + if (lobbyCallerId.StartsWith("+")) + { + // Phone number + participantToMove = new PhoneNumberIdentifier(lobbyCallerId); + } + else if (lobbyCallerId.StartsWith("8:acs:")) + { + // ACS Communication User + participantToMove = new CommunicationUserIdentifier(lobbyCallerId); + } + else + { + return Results.BadRequest("Invalid participant format. Use phone number (+1234567890) or ACS user ID (8:acs:...)"); + } + + var response = await targetConnection.MoveParticipantsAsync(options: new([participantToMove], lobbyConnectionId)); + var rawResponse = response.GetRawResponse(); + if (rawResponse.Status >= 200 && rawResponse.Status <= 299) + { + msgLog.AppendLine().AppendLine("Move Participants operation completed successfully."); + } + else + { + throw new Exception($"Move Participants operation failed with status code: {rawResponse.Status}"); + } + + Console.WriteLine(msgLog.ToString()); + return Results.Text(msgLog.ToString(), "text/plain"); + } + catch (Exception ex) + { + Console.WriteLine($"Error in manual move participants operation: {ex.Message}"); + return Results.BadRequest(new + { + Success = false, + Error = ex.Message, + Message = "Move participants operation failed." + }); + } + #endregion + } + else if (parsedEvent is MoveParticipantSucceeded moveParticipantSucceeded) + { + // added logs to avoid multiple logs for the same callback + msgLog.AppendLine($""" + ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ + Received event: {parsedEvent.GetType()} + Call Connection Id: {moveParticipantSucceeded.CallConnectionId} + Correlation Id: {moveParticipantSucceeded.CorrelationId} + """); + } + else if (parsedEvent is CallDisconnected callDisconnected) + { + // added logs to avoid multiple logs for the same callback + msgLog.AppendLine($""" + ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ + Received event: {parsedEvent.GetType()} + Call Connection Id: {callDisconnected.CallConnectionId} + + """); + } + else + { + // msgLog.AppendLine($"Received event: {parsedEvent.GetType()}"); + } + } + // Log the final message + if (0 != msgLog.Length) + { + Console.WriteLine(msgLog.ToString()); + } + return Results.Text((0 == msgLog.Length) ? string.Empty : msgLog.ToString(), "text/plain"); +}).Produces(StatusCodes.Status200OK); + +#endregion + +#region Lobby Call Support Workflow Endpoints +app.MapPost("/TargetCallToAcsUser(Create)", async (string acsTarget, ILogger logger) => +{ + StringBuilder msgLog = new(); + msgLog.AppendLine(""" + + ~~~~~~~~~~~~ /TargetCall(Create) ~~~~~~~~~~~~ + """); + + Uri callbackUri = new(new Uri(callbackUriHost), "/api/callbacks"); + CallInvite callInvite = new(new CommunicationUserIdentifier(acsTarget)); + var createCallOptions = new CreateCallOptions(callInvite, callbackUri) { + CallIntelligenceOptions = new CallIntelligenceOptions + { + CognitiveServicesEndpoint = new Uri("https://cognitive-service-waferwire.cognitiveservices.azure.com/") + }}; + CreateCallResult createCallResult = await client.CreateCallAsync(createCallOptions); + + targetCallConnectionId = createCallResult.CallConnectionProperties.CallConnectionId; + + msgLog.Append($""" + TargetCall: + ----------- + From: Call Automation + To: {acsTarget} + Target Call Connection Id: {targetCallConnectionId} + Correlation Id: {createCallResult.CallConnectionProperties.CorrelationId} + """); + + Console.WriteLine(msgLog.ToString()); + return Results.Text(msgLog.ToString(), "text/plain"); +}).WithTags("Lobby Call Support APIs"); +app.MapGet("/GetParticipants/{callConnectionId}", async (string callConnectionId, ILogger logger) => +{ + StringBuilder msgLog = new(); + msgLog.AppendLine($""" + + ~~~~~~~~~~~~ /GetParticipants/{callConnectionId} ~~~~~~~~~~~~ + """); + try + { + var callConnection = client.GetCallConnection(callConnectionId); + var participants = await callConnection.GetParticipantsAsync(); + + var participantinfo = participants.Value.Select(p => new + { + p.Identifier.RawId, + Type = p.Identifier.GetType().Name, + PhoneNumber = p.Identifier is PhoneNumberIdentifier phone ? phone.PhoneNumber : null, + AcsUserId = p.Identifier is CommunicationUserIdentifier user ? user.Id : null, + }).OrderBy(p => p.AcsUserId) // to display phone numbers first + .Select(p => new + { + Info = string.IsNullOrWhiteSpace(p.AcsUserId) + ? $"{p.Type} - RawId: {p.RawId}, Phone: {p.PhoneNumber}" // extra space for alignment + : $"{p.Type} - RawId: {p.AcsUserId}" + }); + + if (!participantinfo.Any()) + { + return Results.NotFound(new + { + Message = "No participants found for the specified call connection.", + CallConnectionId = callConnectionId + }); + } + else + { + msgLog.AppendLine($""" + + No of Participants: {participantinfo.Count()} + Participants: + ------------- + {string.Join("\n", participantinfo.Select((p, index) => $"{index + 1}. {p.Info}"))} + """); + Console.WriteLine(msgLog.ToString()); + return Results.Text(msgLog.ToString(), "text/plain"); + } + } + catch (Exception ex) + { + logger.LogError($"Error getting participants for call {callConnectionId}: {ex.Message}"); + return Results.BadRequest(new + { + Error = ex.Message, + CallConnectionId = callConnectionId + }); + } +}).WithTags("Lobby Call Support APIs"); + +#endregion + +app.Run(); diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json new file mode 100644 index 00000000..688b8a42 --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:39947", + "sslPort": 44389 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5142", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7006;http://localhost:5142", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.Development.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json new file mode 100644 index 00000000..3718a2bf --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -0,0 +1,14 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "acsConnectionString": "", + "cognitiveServiceEndpoint": "", + "callbackUriHost": "", + "pmaEndpoint": "", + "acsGeneratedId": "" +} From a2a36ffff742de01e75f6132b0a3e87a948ccacc Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Mon, 28 Jul 2025 15:54:47 +0530 Subject: [PATCH 02/27] Lobby Call Support Sample - added support for web socket to recdive confimration from client app. --- .../LobbyCallSupportSample/Program.cs | 285 ++++++++++++++---- .../LobbyCallSupportSample/appsettings.json | 6 +- 2 files changed, 222 insertions(+), 69 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 087e02e1..dfffdb54 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -4,6 +4,7 @@ using Azure.Messaging; using Azure.Messaging.EventGrid; using Azure.Messaging.EventGrid.SystemEvents; +using System.Net.WebSockets; using System.Text; #region Bootstrap @@ -38,10 +39,18 @@ pmaEndpoint = builder.Configuration["pmaEndpoint"] ?? throw new ArgumentNullException("pmaEndpoint"), - acsGeneratedId = - builder.Configuration["acsGeneratedId"] - ?? throw new ArgumentNullException("acsGeneratedId"), - + acsGeneratedIdForLobbyCall = + builder.Configuration["acsGeneratedIdForLobbyCall"] + ?? throw new ArgumentNullException("acsGeneratedIdForLobbyCall"), + acsGeneratedIdForTargetCall = + builder.Configuration["acsGeneratedIdForTargetCall"] + ?? throw new ArgumentNullException("acsGeneratedIdForTargetCall"), + socketToken = + builder.Configuration["socketToken"] + ?? throw new ArgumentNullException("socketToken"), + confirmMessageToTargetCall = + builder.Configuration["confirmMessageToTargetCall"] + ?? throw new ArgumentNullException("confirmMessageToTargetCall"), // Track which type of workflow call was last created lastWorkflowCallType = string.Empty, // "CallTwo" or "CallThree" acsIdentity = string.Empty, @@ -51,6 +60,9 @@ lobbyCallerId = string.Empty, // User's incoming call callConnectionId2 = string.Empty; // ACS user's redirected call +// Web socket +WebSocket? webSocket = null; + CallAutomationClient client = new(pmaEndpoint: new Uri(pmaEndpoint), connectionString: acsConnectionString); #endregion @@ -85,7 +97,7 @@ toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; // Lobby Call: Answer - if (toCallerId.Contains(acsGeneratedId)) + if (toCallerId.Contains(acsGeneratedIdForLobbyCall)) { #region Answer Call Uri callbackUri = new (new Uri(callbackUriHost), $"/api/callbacks"); @@ -110,8 +122,7 @@ User Call(Inbound) Answered by Call Automation. Lobby Call answered successfully. """); #endregion - } - + } else { //msgLog.AppendLine($"Call filtered out - not matching expected scenarios"); @@ -193,67 +204,19 @@ Lobby Call answered successfully. """); // TODO: Notify Target Cal user - // By Recognition or pop up in Client app - - #region Move Participant - try - { - msgLog.AppendLine($""" - ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ - Move Participant operation started.. - Source Caller Id: {lobbyCallerId} - Source Connection Id: {lobbyConnectionId} - Target Connection Id: {targetCallConnectionId} - """); - - // Get the target connection - CallConnection targetConnection = client.GetCallConnection(targetCallConnectionId); - - // Get participants from source connection for reference - CallConnection sourceConnection = client.GetCallConnection(lobbyConnectionId); - - // Create participant identifier based on the input - CommunicationIdentifier participantToMove; - if (lobbyCallerId.StartsWith("+")) - { - // Phone number - participantToMove = new PhoneNumberIdentifier(lobbyCallerId); - } - else if (lobbyCallerId.StartsWith("8:acs:")) - { - // ACS Communication User - participantToMove = new CommunicationUserIdentifier(lobbyCallerId); - } - else - { - return Results.BadRequest("Invalid participant format. Use phone number (+1234567890) or ACS user ID (8:acs:...)"); - } - - var response = await targetConnection.MoveParticipantsAsync(options: new([participantToMove], lobbyConnectionId)); - var rawResponse = response.GetRawResponse(); - if (rawResponse.Status >= 200 && rawResponse.Status <= 299) - { - msgLog.AppendLine().AppendLine("Move Participants operation completed successfully."); - } - else - { - throw new Exception($"Move Participants operation failed with status code: {rawResponse.Status}"); - } - - Console.WriteLine(msgLog.ToString()); - return Results.Text(msgLog.ToString(), "text/plain"); - } - catch (Exception ex) + // By pop up in Client app + if (webSocket is null || webSocket.State != WebSocketState.Open) { - Console.WriteLine($"Error in manual move participants operation: {ex.Message}"); - return Results.BadRequest(new - { - Success = false, - Error = ex.Message, - Message = "Move participants operation failed." - }); + msgLog.AppendLine("ERROR: Web socket is not available."); + return Results.NotFound("Message not sent"); + // throw new ArgumentNullException("web socket is not available."); } - #endregion + + // Notify Client + var msg = System.Text.Encoding.UTF8.GetBytes(confirmMessageToTargetCall); + await webSocket.SendAsync(new ArraySegment(msg), WebSocketMessageType.Text, true, CancellationToken.None); + msgLog.AppendLine($"Target Call notified with message: {confirmMessageToTargetCall}"); + return Results.Ok("Target Call notified with message: {confirmMessageToTargetCall}"); } else if (parsedEvent is MoveParticipantSucceeded moveParticipantSucceeded) { @@ -380,6 +343,194 @@ Move Participant operation started.. } }).WithTags("Lobby Call Support APIs"); -#endregion +#endregion + +#region Websocket implementation +app.UseWebSockets(); +app.Map($"/ws/{socketToken}", async context => +{ + + Console.WriteLine("Received WEB SOCKET request."); + if (context.WebSockets.IsWebSocketRequest) + { + webSocket = await context.WebSockets.AcceptWebSocketAsync(); + var buffer = new byte[1024 * 4]; + + //// 1. Send message to JS + //var msg = "A user is waiting in lobby, do you want to add the user to your call?"; + //var bytes = Encoding.UTF8.GetBytes(msg); + //await webSocketFromContext.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text, true, CancellationToken.None); + + // 2. Receive client response + // Keep alive with a read loop + while (webSocket.State == WebSocketState.Open) + { + try + { + var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + var jsResponse = Encoding.UTF8.GetString(buffer, 0, result.Count); + Console.WriteLine($"Received response from Client App: {jsResponse}"); + // Move participant to target call if response is "yes" + + if (result.MessageType == WebSocketMessageType.Close) + { + Console.WriteLine($"result.MessageType: {result.MessageType}"); + await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None); + } + else + { + // Process incoming message or ignore + if (!jsResponse.Equals("no", StringComparison.OrdinalIgnoreCase)) + { + Console.WriteLine($"Move Participant operation begins.."); + // Call the Move Participants API + #region Move Participant + try + { + targetCallConnectionId = jsResponse; + Console.WriteLine($""" + ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ + Move Participant operation started.. + Source Caller Id: {lobbyCallerId} + Source Connection Id: {lobbyConnectionId} + Target Connection Id: {targetCallConnectionId} + """); + + // Get the target connection + CallConnection targetConnection = client.GetCallConnection(targetCallConnectionId); + Console.WriteLine("targetConnection fetched.."); + + // Get participants from source connection for reference + CallConnection sourceConnection = client.GetCallConnection(lobbyConnectionId); + Console.WriteLine("sourceConnection fetched.."); + + // Create participant identifier based on the input + CommunicationIdentifier participantToMove; + if (lobbyCallerId.StartsWith("+")) + { + // Phone number + participantToMove = new PhoneNumberIdentifier(lobbyCallerId); + } + else // if (lobbyCallerId.StartsWith("8:acs:")) + { + // ACS Communication User + participantToMove = new CommunicationUserIdentifier(lobbyCallerId); + } + + var response = await targetConnection.MoveParticipantsAsync(options: new([participantToMove], lobbyConnectionId)); + var rawResponse = response.GetRawResponse(); + Console.WriteLine($"rawResponse: {rawResponse}"); + if (rawResponse.Status >= 200 && rawResponse.Status <= 299) + { + Console.WriteLine(); + Console.WriteLine("Move Participants operation completed successfully."); + } + else + { + throw new Exception($"Move Participants operation failed with status code: {rawResponse.Status}"); + } + + // Console.WriteLine(msgLog.ToString()); + // return Results.Text(msgLog.ToString(), "text/plain"); + } + catch (Exception ex) + { + Console.WriteLine($"Error in move participants operation: {ex.Message}"); + //return Results.BadRequest(new + //{ + // Success = false, + // Error = ex.Message, + // Message = "Move participants operation failed." + //}); + } + #endregion + + } + } + + } + catch (Exception ex) + { + Console.WriteLine("----- Web socket error -----"); + Console.WriteLine(ex.Message); + Console.WriteLine("----- End: Web socket error -----"); + + //throw; + } + } + + //var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + //var jsResponse = Encoding.UTF8.GetString(buffer, 0, result.Count); + //Console.WriteLine($"Received from JS: {jsResponse}"); + //// Move participant to target call if response is "yes" + //if (jsResponse.Equals("yes", StringComparison.OrdinalIgnoreCase)) + //{ + // Console.WriteLine($"TODO: Move Participant"); + // // Call the Move Participants API + // #region Move Participant + // try + // { + // Console.WriteLine($""" + // ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ + // Move Participant operation started.. + // Source Caller Id: {lobbyCallerId} + // Source Connection Id: {lobbyConnectionId} + // Target Connection Id: {targetCallConnectionId} + // """); + + // // Get the target connection + // CallConnection targetConnection = client.GetCallConnection(targetCallConnectionId); + + // // Get participants from source connection for reference + // CallConnection sourceConnection = client.GetCallConnection(lobbyConnectionId); + + // // Create participant identifier based on the input + // CommunicationIdentifier participantToMove; + // if (lobbyCallerId.StartsWith("+")) + // { + // // Phone number + // participantToMove = new PhoneNumberIdentifier(lobbyCallerId); + // } + // else // if (lobbyCallerId.StartsWith("8:acs:")) + // { + // // ACS Communication User + // participantToMove = new CommunicationUserIdentifier(lobbyCallerId); + // } + + // var response = await targetConnection.MoveParticipantsAsync(options: new([participantToMove], lobbyConnectionId)); + // var rawResponse = response.GetRawResponse(); + // if (rawResponse.Status >= 200 && rawResponse.Status <= 299) + // { + // Console.WriteLine(); + // Console.WriteLine("Move Participants operation completed successfully."); + // } + // else + // { + // throw new Exception($"Move Participants operation failed with status code: {rawResponse.Status}"); + // } + + // // Console.WriteLine(msgLog.ToString()); + // // return Results.Text(msgLog.ToString(), "text/plain"); + // } + // catch (Exception ex) + // { + // Console.WriteLine($"Error in manual move participants operation: {ex.Message}"); + // //return Results.BadRequest(new + // //{ + // // Success = false, + // // Error = ex.Message, + // // Message = "Move participants operation failed." + // //}); + // } + // #endregion + + //} + } + else + { + context.Response.StatusCode = 400; + } +}); +#endregion app.Run(); diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json index 3718a2bf..c5656676 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -9,6 +9,8 @@ "acsConnectionString": "", "cognitiveServiceEndpoint": "", "callbackUriHost": "", - "pmaEndpoint": "", - "acsGeneratedId": "" + "confirmMessageToTargetCall": "A user is waiting in lobby, do you want to add the lobby user to your call?", + "acsGeneratedIdForLobbyCall": "", + "acsGeneratedIdForTargetCall": "", + "socketToken": "" } From cec29b7e370271f3d1185d3584aea29b02c8e623 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Mon, 28 Jul 2025 21:13:11 +0530 Subject: [PATCH 03/27] LobbyCallSupportSample - testing and code tweaks --- .../LobbyCallSupportSample/Program.cs | 153 ++++++------------ .../LobbyCallSupportSample/appsettings.json | 5 +- 2 files changed, 49 insertions(+), 109 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index dfffdb54..72e34208 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -36,15 +36,15 @@ callbackUriHost = builder.Configuration["callbackUriHost"] ?? throw new ArgumentNullException("callbackUriHost"), - pmaEndpoint = - builder.Configuration["pmaEndpoint"] - ?? throw new ArgumentNullException("pmaEndpoint"), - acsGeneratedIdForLobbyCall = - builder.Configuration["acsGeneratedIdForLobbyCall"] - ?? throw new ArgumentNullException("acsGeneratedIdForLobbyCall"), - acsGeneratedIdForTargetCall = - builder.Configuration["acsGeneratedIdForTargetCall"] - ?? throw new ArgumentNullException("acsGeneratedIdForTargetCall"), + acsGeneratedIdForLobbyCallReceiver = + builder.Configuration["acsGeneratedIdForLobbyCallReceiver"] + ?? throw new ArgumentNullException("acsGeneratedIdForLobbyCallReceiver"), + acsGeneratedIdForTargetCallReceiver = + builder.Configuration["acsGeneratedIdForTargetCallReceiver"] + ?? throw new ArgumentNullException("acsGeneratedIdForTargetCallReceiver"), + acsGeneratedIdForTargetCallSender = + builder.Configuration["acsGeneratedIdForTargetCallSender"] + ?? throw new ArgumentNullException("acsGeneratedIdForTargetCallSender"), socketToken = builder.Configuration["socketToken"] ?? throw new ArgumentNullException("socketToken"), @@ -56,15 +56,15 @@ acsIdentity = string.Empty, // Call connection IDs targetCallConnectionId = string.Empty, - lobbyConnectionId = string.Empty, // User's incoming call - lobbyCallerId = string.Empty, // User's incoming call + lobbyConnectionId = string.Empty, // User's incoming call connection id + lobbyCallerId = string.Empty, // User's incoming caller id callConnectionId2 = string.Empty; // ACS user's redirected call // Web socket WebSocket? webSocket = null; CallAutomationClient client = - new(pmaEndpoint: new Uri(pmaEndpoint), connectionString: acsConnectionString); + new(connectionString: acsConnectionString); #endregion #region Event Handler @@ -97,13 +97,13 @@ toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; // Lobby Call: Answer - if (toCallerId.Contains(acsGeneratedIdForLobbyCall)) + if (toCallerId.Contains(acsGeneratedIdForLobbyCallReceiver) || toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) { #region Answer Call Uri callbackUri = new (new Uri(callbackUriHost), $"/api/callbacks"); AnswerCallOptions options = new (incomingCallEventData.IncomingCallContext, callbackUri) { - OperationContext = "LobbyCall", + OperationContext = !toCallerId.Contains(acsGeneratedIdForTargetCallReceiver) ? "LobbyCall" : "OtherCall", CallIntelligenceOptions = new CallIntelligenceOptions { CognitiveServicesEndpoint = new Uri("https://cognitive-service-waferwire.cognitiveservices.azure.com/") @@ -111,16 +111,33 @@ }; AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); - lobbyConnectionId = answerCallResult.CallConnection.CallConnectionId; - - msgLog.AppendLine($""" - User Call(Inbound) Answered by Call Automation. - From Caller Raw Id: {fromCallerId} - To Caller Raw Id: {toCallerId} - Lobby Call Connection Id: {lobbyConnectionId} - Correlation Id: {incomingCallEventData.CorrelationId} - Lobby Call answered successfully. - """); + + if (toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) + { + targetCallConnectionId = answerCallResult.CallConnection.CallConnectionId; + + msgLog.AppendLine($""" + Target Call(Inbound) Answered by Call Automation. + From Caller Raw Id: {fromCallerId} + To Caller Raw Id: {toCallerId} + Target Call Connection Id: {targetCallConnectionId} + Correlation Id: {incomingCallEventData.CorrelationId} + Target Call answered successfully. + """); + } + else + { + lobbyConnectionId = answerCallResult.CallConnection.CallConnectionId; + + msgLog.AppendLine($""" + User Call(Inbound) Answered by Call Automation. + From Caller Raw Id: {fromCallerId} + To Caller Raw Id: {toCallerId} + Lobby Call Connection Id: {lobbyConnectionId} + Correlation Id: {incomingCallEventData.CorrelationId} + Lobby Call answered successfully. + """); + } #endregion } else @@ -175,6 +192,9 @@ Lobby Call answered successfully. #region Play lobby waiting message // setup cognitive service end point + Console.WriteLine($""" + Playing Media to Lobby Call.. + """); CallMedia callMedia = !string.IsNullOrEmpty(callConnected.CallConnectionId) ? client.GetCallConnection(callConnected.CallConnectionId).GetCallMedia() : throw new ArgumentNullException("Call connection id is empty"); @@ -380,14 +400,13 @@ Lobby Call answered successfully. else { // Process incoming message or ignore - if (!jsResponse.Equals("no", StringComparison.OrdinalIgnoreCase)) + if (jsResponse.Equals("yes", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine($"Move Participant operation begins.."); // Call the Move Participants API #region Move Participant try { - targetCallConnectionId = jsResponse; Console.WriteLine($""" ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ Move Participant operation started.. @@ -398,11 +417,9 @@ Move Participant operation started.. // Get the target connection CallConnection targetConnection = client.GetCallConnection(targetCallConnectionId); - Console.WriteLine("targetConnection fetched.."); // Get participants from source connection for reference CallConnection sourceConnection = client.GetCallConnection(lobbyConnectionId); - Console.WriteLine("sourceConnection fetched.."); // Create participant identifier based on the input CommunicationIdentifier participantToMove; @@ -411,7 +428,7 @@ Move Participant operation started.. // Phone number participantToMove = new PhoneNumberIdentifier(lobbyCallerId); } - else // if (lobbyCallerId.StartsWith("8:acs:")) + else { // ACS Communication User participantToMove = new CommunicationUserIdentifier(lobbyCallerId); @@ -419,7 +436,6 @@ Move Participant operation started.. var response = await targetConnection.MoveParticipantsAsync(options: new([participantToMove], lobbyConnectionId)); var rawResponse = response.GetRawResponse(); - Console.WriteLine($"rawResponse: {rawResponse}"); if (rawResponse.Status >= 200 && rawResponse.Status <= 299) { Console.WriteLine(); @@ -429,19 +445,10 @@ Move Participant operation started.. { throw new Exception($"Move Participants operation failed with status code: {rawResponse.Status}"); } - - // Console.WriteLine(msgLog.ToString()); - // return Results.Text(msgLog.ToString(), "text/plain"); } catch (Exception ex) { Console.WriteLine($"Error in move participants operation: {ex.Message}"); - //return Results.BadRequest(new - //{ - // Success = false, - // Error = ex.Message, - // Message = "Move participants operation failed." - //}); } #endregion @@ -455,76 +462,8 @@ Move Participant operation started.. Console.WriteLine(ex.Message); Console.WriteLine("----- End: Web socket error -----"); - //throw; } } - - //var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); - //var jsResponse = Encoding.UTF8.GetString(buffer, 0, result.Count); - //Console.WriteLine($"Received from JS: {jsResponse}"); - //// Move participant to target call if response is "yes" - //if (jsResponse.Equals("yes", StringComparison.OrdinalIgnoreCase)) - //{ - // Console.WriteLine($"TODO: Move Participant"); - // // Call the Move Participants API - // #region Move Participant - // try - // { - // Console.WriteLine($""" - // ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ - // Move Participant operation started.. - // Source Caller Id: {lobbyCallerId} - // Source Connection Id: {lobbyConnectionId} - // Target Connection Id: {targetCallConnectionId} - // """); - - // // Get the target connection - // CallConnection targetConnection = client.GetCallConnection(targetCallConnectionId); - - // // Get participants from source connection for reference - // CallConnection sourceConnection = client.GetCallConnection(lobbyConnectionId); - - // // Create participant identifier based on the input - // CommunicationIdentifier participantToMove; - // if (lobbyCallerId.StartsWith("+")) - // { - // // Phone number - // participantToMove = new PhoneNumberIdentifier(lobbyCallerId); - // } - // else // if (lobbyCallerId.StartsWith("8:acs:")) - // { - // // ACS Communication User - // participantToMove = new CommunicationUserIdentifier(lobbyCallerId); - // } - - // var response = await targetConnection.MoveParticipantsAsync(options: new([participantToMove], lobbyConnectionId)); - // var rawResponse = response.GetRawResponse(); - // if (rawResponse.Status >= 200 && rawResponse.Status <= 299) - // { - // Console.WriteLine(); - // Console.WriteLine("Move Participants operation completed successfully."); - // } - // else - // { - // throw new Exception($"Move Participants operation failed with status code: {rawResponse.Status}"); - // } - - // // Console.WriteLine(msgLog.ToString()); - // // return Results.Text(msgLog.ToString(), "text/plain"); - // } - // catch (Exception ex) - // { - // Console.WriteLine($"Error in manual move participants operation: {ex.Message}"); - // //return Results.BadRequest(new - // //{ - // // Success = false, - // // Error = ex.Message, - // // Message = "Move participants operation failed." - // //}); - // } - // #endregion - - //} } else { diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json index c5656676..bbbb8c47 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -10,7 +10,8 @@ "cognitiveServiceEndpoint": "", "callbackUriHost": "", "confirmMessageToTargetCall": "A user is waiting in lobby, do you want to add the lobby user to your call?", - "acsGeneratedIdForLobbyCall": "", - "acsGeneratedIdForTargetCall": "", + "acsGeneratedIdForLobbyCallReceiver": "", + "acsGeneratedIdForTargetCallReceiver": "", + "acsGeneratedIdForTargetCallSender": "", "socketToken": "" } From e496346a150aac6cd4988a5b12616ed298d96529 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Tue, 29 Jul 2025 16:30:22 +0530 Subject: [PATCH 04/27] Lobby Call Support Sample - final checkin --- .../LobbyCallSupportSample/Program.cs | 7 +- .../Resources/Lobby_Call_Support_Scenario.jpg | Bin 0 -> 128065 bytes .../LobbyCallSupportSample/appsettings.json | 3 +- .../LobbyCallSupportSample/readme.md | 78 ++++++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/Resources/Lobby_Call_Support_Scenario.jpg create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/readme.md diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 72e34208..d16113ad 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -51,6 +51,9 @@ confirmMessageToTargetCall = builder.Configuration["confirmMessageToTargetCall"] ?? throw new ArgumentNullException("confirmMessageToTargetCall"), + textToPlayToLobbyUser = + builder.Configuration["textToPlayToLobbyUser"] + ?? throw new ArgumentNullException("textToPlayToLobbyUser"), // Track which type of workflow call was last created lastWorkflowCallType = string.Empty, // "CallTwo" or "CallThree" acsIdentity = string.Empty, @@ -199,7 +202,7 @@ Playing Media to Lobby Call.. client.GetCallConnection(callConnected.CallConnectionId).GetCallMedia() : throw new ArgumentNullException("Call connection id is empty"); TextSource textSource = - new("You are currently in a lobby call, we will notify the admin that you are waiting.") + new(textToPlayToLobbyUser) { VoiceName = "en-US-NancyNeural" }; @@ -274,7 +277,7 @@ Playing Media to Lobby Call.. #endregion #region Lobby Call Support Workflow Endpoints -app.MapPost("/TargetCallToAcsUser(Create)", async (string acsTarget, ILogger logger) => +app.MapPost("/TargetCallToAcsUser(Call Replaced with client app)", async (string acsTarget, ILogger logger) => { StringBuilder msgLog = new(); msgLog.AppendLine(""" diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Resources/Lobby_Call_Support_Scenario.jpg b/LobbyCallSupportSample/LobbyCallSupportSample/Resources/Lobby_Call_Support_Scenario.jpg new file mode 100644 index 0000000000000000000000000000000000000000..92225d4e602310278e4a69aed681d388a4290064 GIT binary patch literal 128065 zcmeFa2V9fOwkRGqVpl{6D#a3-geD~*U4?*jAqk-clul@p(Cgk-x&j8ID@aKKL3#;A zrFSWzhbX-xy~B%V-?R6=|9j4P=a&C{?|0vx{K&VMS>McBYu3!HDQj}rfA|$}UPDz~ z6>#JT0C0r<0UVAV=~q`)Hovd0tE#RA{WYNxKo3W60sv0VZWw*FyVnejjISO4`s*7% z(jHo3AN_d#oj}ibqxVPd06@3!-@*Au(I>5}v6gg%@AN+&483qVv8;5M)%I8T#t+!y zS6KcB?CJK%jgE8w2aJL1E7M^sI()zfaMDSaLVK_Y4oqZL)$fa5+|K57y8E* z;0Uk=Tmz^BoB@^q5jrFexCsygNF5FVlmQGs{Rlt48R+5Yv7eR^- zCr_R_!*u4<>2s$~o;=HZ_8ims^UUW@ow>kr;XDf+KK~<=BR}3`IC_Hq;`!4jPt#-n zo#F5!fceBxnG@F-j(`9^F&|-IK5|$K;G&EBCx#>R@KHi;`mQYfFnOK9A!LqocY9s>tZKaSTEhtGjP2K5`P%=y0aU|Eg^juj&S$* zB{H?3u!~LVmOjz~miI1>@WrJi zS}Xp_u4t~McB!kxQ`q9*Y1Cj&Q-9?`WL_XUIdBo;Z24%T7-<^da`9rb0?RK+CR-sO zUy1g>8}0hvugPp>YEuM0JcF+YE^-87)D8i0D{>*4gxtbf0cQCY_{1T=tuIOJ$;<5> z-Q&?nQ8z}p+^Iu=Q{W*0_kz)L`F({CuiA2~-;?^Nfp6Y1QWPn(rI8;5|~TLlxu$F)C^x4O&}E~IU>RNWa<_gd3s6BhpE5Uku*0gKCmz#0Ze@R`T`ir8_Hu`HGfOH@k`%)$AKz!+y*Kaxg zg`#BI^i?*$qDO{5BLmqr8&ctcmpvQhf6H+u?5b~R# z{K{`Ry45pP&hVG)9Is0eHf6g8r2WP;({DM-S{@%+iyqo%810B5oj!kR>34R1%aKd$ z$&!!ypA!00LVxPepRMfAe(2Ah`qwe^&#~;!(f&_+=ueCBHv{-ji}5d3`hU)*er{Kq zLDVIFdsMvxoTY8lr%L`Xd2w&xy)zD8vTrecHVegZsdFQC9vCp=<5|RS%Y}~gqr#yvsYtziFm^P_Qz>W)BS#$ z()Y|Mq8qR^yrx--p}Ay~C^tVo+-x&<6@)&}rueI+=%yRb5SW})P0S%x z;d5;*=KQ`Y2jOxosXLuj`85{oo-ZDJ@Jw`WIx8QNp!lw-Lq4U;XMJcyC)r9$xur}x zPtK(;<+Ie?*DIQr(-rpRLI@RyfIT+$zEFVPHmGxu-Ji(~70?S4+WLXhkf0_ckSQ zr=r{sdFee`JesrUbMFR^n`;rv%Jq%>=OI!n4QdRq*8a}(?PtnV6yk*jOY%c36vNC; zYi<;pA36TGYd`1WN97x*XJP$yUkj@ppx@7X35yPP`W+Sj8U1J6pECGU5B_WmfA$A| z_KE*<#)a+4{DE1e8Mb&C&ja~0p1b#VZ#M%I+z^+wlub%!ic_eOeoAKw?oI4UrdgVQ zj}NLIvEQs>Un`%d7;Czt2+&~Npn99TNVlLkWz9pi@E3|xkeHdX6R zl6Jl0Gt(?J`kdWe^$IGlRs^Q-RoL(IzD0)`2lTo*hZfpO9s;NwV=FJ8YBWFjR4ZZX zd#jkYy~Z#K)EaCqJ| zK*5h~*xv&K@4wp5isOC+xb}PM{|35=MCuLQm@G8~TV`ftS~LmeqT=f_(S+bPLG5}7 zJr!+)jviB6{g|@dyZ9+AAtF8|DP-F^(!=3Csm#DP&Ou@SQN_75ABs=vu1At*qcV?!@@JIpXcsOfqEtU5_%Qxy_K7FMAxme5pm2pBpvhivg9BRDBJR&HeFJQ#+aqu_HQ9V~#uy5l9tJ zr`qjvJ?r$~KKnFPAXPSPJ&q=^{0d-H{=X5^|JBJ?{5L+?H04AMEcH%1*iGrWu;R;I z#^Gi?@D;GT@|T}16{2!l+)x>IWz1r7eEg0YMB8#`%=CKQKox^)R{Q`1uH9fgCN8B8 zR~eOW+G9yNxQLJD`cOcHaK!y@0Fg-)8C_652yb9wj$Ld;nNE|FOEn;r>Pk z1(&1JW;@p3G(|}Re)?nTKZHp;b@9XQ47{1$LNfAvtXYow*$!Q)?=BVuj!F;+8_pq> zK_T~yX(C?h^|5LVsE?~0iFLqHQdZ%< zKA*HILz1lnUDiBS@!w{&wEB<(P93X$WKPADN?#pI{P@O&Z2X(vO1L|Wx=q<_FmT${ zavP;&^v?;y?+rNcsYI0%oeR`UqFZ}r!*%y4+7%2M@fL5Ix$0R?+A>%qN?l1Z76?n_ z-a7;|0(d|CLl*y?iR=e&tyUj;A*KW$N8F<>=JG=cO1X%8eKL$nMaL z1vMao%hZAOyGBB>swf)l9SRczs!+-_BN1>dJsBMnMReR)!>b(z=dHOzfR)$sxZ=-4 zRrJaF0N;FyieywYI~f79-;bAh_b&O~$enwRqoahlad_d2;&kZh#E>RUJ%{;4P zQ1QK zd!Jk@N~`VkI^lR1{0_f&c3NcP)E&N|h1LWt1V)gvqUEZ<;bOE;W;NY8rjCwZ*QzdZ znM7u_zcI;8T==`c)(u6u(5`IGmafk=nqIE1uOJI~U)? z#Z|4l(Blc7v459EAmEX*$;TCf7T0=<^i0QT)@D{J@FBude%RUB(YOq0qNmn3AqomY zdEK4w5s*Z@c_QTw#9}+^&DjR=HWSBG>$9eLo6R<|w}#HR7PVu`k{8?ha&>}~y>rYBnq+;?GR6*OZasF%btPgTcNlx7yB^iscp9c!GXQ!-9 z(u9d#r_#cg@kR=dXItYxDKpNVvQ>AAO3L?ws8rn>wSse7C2lZ51J?D5@a*tS*Tdw;^v(cUD5$ zM|F!oY2J1upINsxGTzZasZf7# z)`909eh$w$o@oU1a4>5i5T(r$hno{}QPKEo4pk-k(-RqymW7&+%BcDVokgbM&qCT! zRM5uSq;@1rt{Hw1YN**W917#GcJP6n#?+456RF{c0H!orTCcElsf|nbtPrlid_d@x zY-C}<{7Xwjhl}6%l0Wms`HBROgt*purTa^7oL$eo)mPIs!iE@Sz=>)yQHrW%oTLd1 zcsJc_q^tMQZmrHkqD;7fTwtNmjQ!WQ{wC&XoH;&aSL)|0R%E0GTE?aFjAe;pxvKp^ zgR5@NDQOpx(w^2Z8C5;G@`A1G8^@lI;(B&GGmw7IpQ~77-wYZ{2eR2;#BnC?!aM`5 zR;N>)5v;H(v-P>c{u0FCriu+^-8OhnLR--K!x#OgfXcgMZQY}I&YPmkRipf6<+3cDEaaUK%ho3eX;%h@_bY~*Kzs*>00FM)=W#9Bmv@Dw+3^Wb78DAT#8nYt zAtSAV*yWdLOvp__HlhZ(fL(I#XFRqf$FBJ4mEgD(s$|mPo8vx$6#sQphw;QEEjBn( zrwHY2&g7{+0A?=%nP0aP8r#v`9kj zyvhKIqIdFZ*M~N)?tR6oKC4UN(I3Ii=igs|@M6at^oCm+BM=i*4=S_A20s7#xI=Ot z+-@QwWbT+4?|{RkyPR3UX4X3&X}2j94jDiOfn4&}mG4eSnv+?-&9q3DSddGFB>P_G z%0!e#ka9YAc|Pg~mv&L?IcFYx7}HY;?UZNpbec2UU%B8B;%Yj)atP23nvC%=asOO2 z{2B+3z}yi^zBf!)H=ti=YZkHlUDV{uYI;ks#4?5}Jg&wFcf)Jj=fCmH_1^KWTT9;e z|A1_Qnrm`uo>@-CiWwMy7RtdM;CCk<$ zezAvQer@-2NZUV*;_`R!Pq)aEaz&SnxWFci+ z;P+lcxJXd;17(`;wHcV|(7TXv`Eyrm0Eq+-~_vJ%xgcD~q8M zP^h%vL<}|37(DOk-vnA&61}oi}6f2<* zN7Af7Co*)0f-hX%%TS?TH+wy&6V{Z}AbOII0(w;dTu}-_;A^kH#Sr?p7 zm>o|I*7He2^+LB!;O8)xa;c$gvt>xQWMPbKILFhn(6aKNxb2B@#e%$x#&~m5dG8FL zT9Z|pr(AU7Ygdsrmr5FEC2V_fm8~tzO3TqTFWZuty|+k8MP**)F6djzxrk4X`R>Te z7sd8vHxrWdj}eL`*F}pxH(tfI8@CtfNej{p2D~c5I@jrE1S4t>0XacQKAGQ?JQVdf zFtZ)k05r)Oi98EYoFaXqMaMaA2JGpy^q zgD1v)5%}g{+PFb#22~-Iz)^kPeN)gTd;;i!zsfmtFOoR07~fEt%NDOhRsXWHu z+EZ=_VbkC#kve(xw4jwLtm%FN1~R*Z#+QhvibCNkbN!_sywD;hgaz*juKNRBgLfwq zp%ubeLGi^?2Gc{)*uLcJH*-wuEb@nzHJ?HJg-vWTi1;Pnyacd96$Jr{1Il_h2Tw{} zIX26yS!|@)wpNsp9tjJ~S5r`0RU`?B?kFoigN?q?mXeywftq5-(^@z8L2RjnRau?^ zG9j~w=DyIs<;8gj=-WoF%et&q3=@&_5OlZL)vJl}L@YMLX%$z8aBo#b!SZsJ6V?YZ zcRP=7kMoe&-Iy3jpX>_4@>_Jha?6S1&t>0FJwFjYfd;8oQQFNA2qb7*YKXL)d$}4F zA6R)lF!^rF_p$Zpxf%?Qi-ze6V2 zaNDOB!A!vxzbxz3MoP@Q)Nvn>qOc(Yg8CiQ#J+qj@fp>`h# z$siXxAcK=$nXkIr;Ckl)zIwWC=5=Jbx}5=d(O_exehryBiY^OeHYzpfabQcCqMT`R zuuOYfq3;FmY3hvBh)@$VtG1vFzyfNi(lb2|Z3rLSXZ`07DpeyxJ=ThnJ#VDl*mg;w zKDd?rG5eywNN$sfLq^1uwPD8d^vE=;CGi8MD0&-lYW1T87&yb=xW~G zc`H7fl98j04ns(fWDipWd$$);;Dx;8ecGgiMR;q~-8XgF$zhIF3}$Uq)uQ-7t=1 z&;H0u8#^1Sxf|iT%BY&>M$b%UFeXxB>aX-vUK!+n%?@5ItGr-9#4+zRCXlFlo-|q; zQu>xG1RwYEi9St<-C!f#t=kN{NtT%1v0g(~nl`(dHpu5R-y|cn^FxX*3%-q)Ql0E5 zDZy}aW+f0@h6V{{CwW78zto#8_I&6;Xot$aGZ(U(Q0LMtF9Z5s45&P7u;BC!+{SYs z(e*7~S3c+QEdfN4IB}Q^5(FW^?q(DfUB9RmqBZ1L(um_mysGk1Hgvp?7q@m~&OOd> zH2=6Vj3p>z+$1C3Mts4iT#mu)3b{{^6kn9)2pcN)yfJmAr)S-V^70PiC{|@6YtkxQ z4H6K^j}{0NaFQy&%w{a;BrHdfL3G~j1!pF>DJNGbSsC~tkwO=V`)+P-V(LN|UC?~v z_NXsA$sFW7PW5Fetcvkh{vv(V;)X7^E=;- zUR4#GPC#ApcMc{w&vEW8-=oP2at4tPL=7evqiTi|2G{CcMXyG0&9Qz1wYjSxwA!~@ z{3auVHjxG4e02+tI?=vagt5pOJzeLRl+RYUR+=r3FW9MShFt7|cDDJvUZA_q#GO_D zVfXdsNxZ!QLA@((`E$4$x3`{I&;)8YDSU_~pmv_JDfm2p;#^tdrtB$7<}p$x&nf zJDv`C#~Zj#^TgN>9i>DyHHS==afWiIR2_6Xhjv>DR8|$Aj(OW{YL6c}3PHwbb84%o zgp-nh>_N#^sF#|@*~ZL-yTw-Lu!F|L)z-GT*AxXkE$88iJ*|B!jQQIAfMjvVz^;vw>VN1nRM?R0xsvRyzDib;tbq5 z1ON{*VFw-;0*}*A)@LbhQ38uj)I=!l2ZkI1V07b0?xfO_LqK-VRX=p~;N#8jJBog= z=Ld406TA8ew~xP?z5QP?;QoK|`03iH=8>0tHAzvOcPi^Yhk}VP;!NypxVe%jSy!C9 zV!SGVFGOI}kEMQqJCe|l*HkV;NC1PqLxxjDV3IBEU4v4+v7byonNdxxSCa8NIz3`< z%i)(pB$9F{8Q zY6RYAE+tkBCoUK)70*-+Z8+aHcKY9jk?5BgLo1|?rf{fjqavGY{ zuYCd`ZwkXCJ7rXs(6mp6wSC$xg;SD?Lvl*|EpEm4M{= z@PgM50l!Q(xyCr!$~sEwVu;tW(~wOUyjhY+DuKB;rOW6~Qm)dEwpX!HrIlA-G+1|Z zC!6bbnlFnm-5df&%&Gg8S1r4hb~S0AHJOQw>?B5~jlGQX^bw&VsKNP8@cKFZeVYZGx*{o6nFID>m>@F=`_%3WFvfdbvCf>pc+g0#};7QcW+Hxh! zL+f{T+G>>Y7mcpy?H28@j7*QEFI`pkJ=h~*RjFjeWq&Jd}mAfuYibT0I>Eq6(X`C)Oi=@<9|h zL+nc>p@{e#D00}B9W*}ue*dW&!l3%2!1PQ$U zz9U0kZT6X;R`r0maf5Pal$n*A*yqsV*^#}h;BgvG8bxL;W@k!+?1y!_nGeHA(bIHA`sOD#w@qe+AITGM5qr4>v3XsiYc>}-Wc#w(eLZzk^DH=l`h(6rv8JJN zG3kZ*#a5ZAY4>oZea^HDh4z_FX&v)=qXtMWIehbz6!nTNKjOkuF*Cx6NN zCBr^X$7qSBM97=001hpd5JEGq#z+ll!$3`65t2mihd-*csIh{)0m@Wa!52-xIIGj8 z6=9m1E3BEMRroUf9(UT3mW50k!pz!-SlR4-KJiXWw$sk^r zn-5P$Qo3^larA*w*rJRy-8Q_iiFThH8d21?`xakED1kRQZN4yaIcK3JpEOogrys5z zPjX&>WB8g{L;I6Lv~On)=3)~UODfuArB6#Kw&52&oc28l?T}B5k{2%##9N0xXN_S5 zXR`2Y(i+LmTT`N7?+r9*1TG~X{ZtUxAss5%fH9nh>uKr=IzsD}*lS}9Gq?5m7gx@RaOWy8S?NG{?%*B`L=8G_6YXXAznRYbYHnOMmBfkCSoH~4p$EimK zH>z*N+iy!XaS%ZUxVMS>IxH zpJ-z0<5O;!4MO9TOrYx1+!W1`o2DVC4TC`fMZte&i2eA9?<@Tn_V7xosnC`X;t=5V z-K}scs7TjJGpsAJ1CydQnAFpa$vp&^FPvNhpvnKGdqKZ(|KATB$Kgz>!YnWP>WWG~ z|Dvl~QnfWq+iPC_O!1)`EsQxW-3KoBYqy*{cheKWv1gT59ou)6_lzMk`CvLs6@n8cU7^$uNGBf9Tuo+Sz|-Yb zC4JFNM(=VeI>a+OOXe5%Mf_Z`gSl|ETA^%j$b>T12YFw#^X+ok!YSBB8`YV+ z4NivYsbwO`z8n;zbLYknX40^)2g4XgD$-^@nSm)~&3Jb>=i4Xc7aOi5HqhLewDD+x zp>=i9H${lkkt`*)s?+hIbLgGmSdHDBa##Ok4v(C#(n3Z{a7&WZOhAx+>bB|DwuvCe z5`;$|{Ba~hBB*1$^5Qf}BG~+`gWB6K)KBEb=j0&ZsCXUE&rYAaiyNwK*O-m zz>uQVN5feMVrfdr)m^wS0GDRo?`8dZl33!`Gak`A&VV1D>;FVJYYS5>DZ4t-{BlJg z>k)3Zt8#x?w^MRxU1H8Ra(_PS5CDpQanig}kVa$OXVD4N2mrr)T{>*LTX1rpz7gv- z3xH7RF7f|tV3L}PvMg5G_Y5d8*>O1p$P%nj@&^O=_XbwNY(dBjrAQMIhl|K`E>kRK zXB+6jFEC=WeijBRQajc;EL$SiBe%zv0KMQi!!x^W1vfKHweYp)@n|V94ygqCG9wfc zW4ZIbZS6OJo1E_tEf~bx3krfWP;qC3&}HrBwMoGg-}B=(h-mZ+w--T-#rJ!9jBje5 z9^SDVNoa6soh}t3##9sYUBHl0e5&}&%RdJCl* z8EI3ZKPMwWV7}%F2PvpX?(quuhZXAjb-`AV-IjyD90kuf4bQ&bWJNpA*aKV2=YvRY z8idJ=*^o6TM#I07^=*aKqev;H`v=$EuE-{6LrL#ME^3^{WILz%A`@!t%Y5?K$Egc0 zs=Mz8nCoUk#KeeZ2Y7cMK^+Q8&z8B$Q`e;<6#q6Sk!ks%T5Ww&`RVyrpAs#@B2H7~ z^e*9q&BC(7@!hyxQE~n5+S@1&p72ONI}OMbA1*^F;(uR9t- z#%Q`eBhlLOOS4tl$ETvH$J>-KC8+D)L!JB~rl`d48Uq~L#)KDLxBppn|L?#9>b{_n zB9!-aGS`Dz41euFnEuj%fM}yRe#6pq_h!3}sob@6OTcmc`QK^(4|}dN81;1IEUInh zr|pHHIe7!tas&NfYuZx#T00}-fxcj+#*BBLkxLqzn{`Sm-6>ruA!!pL(w7hBKL_em zQ)PcX>q)=d-m9|=>U9%+-Y=gaY9Ngc;G`H3AO1+^jm9R?eMid>V;(_7MJIQYKwC8{6F=Equ1@0G@2HNb(VN z)S68I%e0yehQuCB+g=jVd@W5*RthyBY!*Fs&mUrgtbinD*2Q+`Xufhj7gA2iA0K>F zIs;)b&cc(nIl~>-ioN5bx=nCCY3a}zp{B{%UXfiam^*3`#I48PqoOh$^denbD%&wt zB6$E~to&NGNc)mk#~5X8VY_VV&Tvul9FVUO5<@-ON33+nTQQT1 z-3doSvuoTfT8xmVR-xY{3%-yJR^Q~W(5Fj0*laseDY5mibR_T_LE?t86fhI#;~ zUHM3_K8BSIaRd7CuD-nK9IRlS}!Yi@2IP-Q;#1X?hsI>SsR78qsG3{ zpm6l1O7`1T=Q;zTG?ioRg~;sFrW^$dN88G1sri{(P$&YSmCVFAI-xO>88_D{&mK%B zPLx%ZVEwHN$Zmp27lfUVkT!;tcG{rfsNQ;K z2E}TgM^9^4Ui-A%>wn%?1}w6kppDX-8qto%5%*NNO_p4G+Teq^U}D(p3#8?1W{1UPs>mfSDGeX@_kKh9!mQGSeaKw7Dqf{+Rk z=6PzBO?&Mx##7;d}YHBb!H-B8Ez;NOi z-|!)zCy1aVu=ch07J3YM?-uS^44KO`Mm{G}D0*!3c&b)bFgfXHaDlCbySYO_B#Wn5 zmLWq-qV9JEOf4}fI}uV$qQM*^1qnih7s{ex3ZZSZY17cwkOZvfdsMfJ{kVmp*-xcI z+JVI)@w3|S^RtX3#wdZop77Xs8~$Qkj!v+IuUYK?P=O3{wz5gz6N1W5YwTg{u_|~2lu2QrEh!7&8`;ea`(L8(Ki)%s9~aY!QGLvvU^Vt z*4%@b!UQr$$ZQX9b;=a9hAh{{q}2(x<4aB|K5aoR#H3a>=VoPl9L%&~BiR@6?YU+V z7GUS3zWK#>NL{z`DBI1F9K;5R$LuA>iBWc8N_!Tz3r*>)U>BC`%0?cI;8Wd&5R#MA zB3W$VnAFyTl=?`srFx$jfyr#!KIHV|HZ+XT_NGW{foR*E`ve0x|Ly00Q{4=S!}fOj z-7oy_e^};CYmcG;5p7`pdmM#s(vlm~S;2<@YjN&Pi(ORbO#hmFXS6P5L9S@FDt=rx z(EZuVh$Se`{W97H;zZ(?=45NDpoRc$-tu+umUN+qcs6h=mzX=TA0_g1b|MxfnZiXm z&0)go84q`dip#~>qu&skz9AMi@*#~OWak7?i-hI2_HmCiWS7BI`BhJB|E#m-J`WQr zhQFvSlb~JcpxxabIwh;>y%lQO)|4Twm;g2InFO3U{co81KN7(R`?fik_Ugx0%f5wp z?;o|kv1E&AE`7H7CWBMdCP#J{zk+<0=5?~a`m&&m{gGOERqYl z82pHsiPePeRz~yXJZtWQjTMrz(F=P<6cdJO))2E$_u)i*SSLiq1vWBMp`_wf^UzaZW^#;ugOIMGit`GMBSU7wT_EW z32#@?&B%Q{yU%DP&Cc%oOrqpDflr%#dvF}8y9lEY;!-Khu&@cK!5j*uWWyG4De-Tu zyD%hIh_voWl)DBrd{YVGsOtlzPv`_i%E}Pl(2!kmC8M(Cm{8U3O(+$SOi0LfLlQqX z=d5@pxGjrLrSgx-mRmIJ?*!c6iTTOq(OT<<+6(~D>GbnI65@YF+W8LV3e|x^sTLqa zNX#_fArxqr#krrrA)6T(>zq{!A7CkJ4hb%9#z#>IOGs9|%dM$|)Hm(=Y_3_QItha@ ztMTJ*9_9YAk-Pyb8u;<>U~+QRs-8w%7U~O{LWmF5a=mmRiI8LMK7cSi1o&UK$Y`3R zHdndbB}`qOL}qQDRn>iink+?jbjQsVSlUL0q1`NDjll;LggisW=V=FnF}abo9Z82; z3X<9%BYp)8nd6RE2fLptkCNU{zFQB=!%ym{K=%j)v^csRuW_)ouilIp2}}cCEk?gx z7sx{gHOJGPKUq+)Dt+P5pqxhyK%!$$%U~LExToXWjjBQ%SDD0v#K0+!GK-9kycYjO z9FTdn3)Bry_1>6m5Unimw}u}REEQ6iZZ5x$cJ9-eaSzmjjA<2Nl88a$dcvOkk} z=?Jx{jnKtN`2~co-zy!7p+(?E{IrNi`M?Z##!CHR@=0Kn>KdxE4dV{IyY+}%_j#&_ zbq(65$-+6EwJqaodFsRavAS#!?ZeSo|{ z04$*PXeU zcd4-zY)&WQ;7VfLs=RlGtt{zuc$VWfoI! zyv=@(5AW2~m3NAgF~sK=wPC&J-m+@9soP=XYV*C?`YS+ zyxicBH=JV8>@Ac20d=KUXF`SA!q7d~-ZOw4+_h4nw%R{9XT1y@-g`HZaDU6)ZzGh- z(v>^Si6wGJE|@u^)q&pcB7xGXgq5WdaDf$cr1Z*I*F-e+!58Q2gz@(+4`V;(c!u

CNWjye`g+=)YXX&sx2M*(x)CFH0)r|9NhI+Z(I!GYq}7*eH-^L~zcW$Vr5fqZRx z)dW*|FJD`b%+eT+_7BygpQoG-3VQZ(Z07mucX^*E*41FwzPAR@%EAc8l7 zdwi&^wF;BXF&GEV=NqRui0T$td1+nC{h+K9* zg_7yjJlnah6Y{*ut++2^7xJYwYouz`ym7I*PBz|k5O(^K!@=Ur;952^S7+ocz&rcn z-;v>wKd!wNJ^NQClkfq!udN1?wpAZ?K;KBvFt`bD7peU%qa(li5Vih##e-I4Dd3;1 zL`c%#TtIR8o2xA{`vO}8Mg1|?l*Ly5wYmN7EI^;il;sb%^w3heS~A*CEeCU;NJ*~?UoZ2uMMz~dCcB%13F`<1 zf(lPXwN!|q9k59{B#S0651WsD5~Vp85ufI6R;A&-xv75$NUj^sY94le(Xn;_CiX`- z5K?+?A9?oeudE!OROb$n))XA97X!9qW35zlC$oxrpecBu8(zts0ytg$w4c=GkB0FVDHbS%~)g_Jxn^|J0Pd$u@pXdFYXLF zE35C`I?`=`+2?{M(@s*Ij&9yYfw}r#*d|vYe6`@Ch zqWR5wxRWRLff)+C%_29&l~N_ld%>|z3%lI{V}^soN$LvNr>D#rYe?}O4tIdLBT$j& z+c5SSHbE~kBS`I6%0Kij)VIa8dru91UlCe8Rzu|wA8xO+a;t{X?O%55Kw_1Qw1V;J zXN`hn-X$@^I&LDKB-8k$2pylkw%!F=D|)_;!OJc zh{m-TejI)h?R(di~T3CZp~==QookGEL<5tBm$CSbYi{&F{EeBh_)9}a*j2x<(xt#zhI#o&J1{ybA zY-w$9CQLa!YQH_VsNnWBHzeEBSaO3gq|TGz-wwXDpY4m~cF3w2j&MvU*}@BYY@Wz8 zUJi@sd^6^eU2>J6kzhR=!tso=F~PHu*Fqs;sEKTvbk-4-m6}Bg@7ghAV$lKjm}a`s z_5P(6z`pqBzv}t_4^PhI(VwPxX(m{oCMzV-1@{Po@Z89|mshgvSS!i!s8>V!K6=Dn zb>RRPn2QE)5WJK(%p2{e{B1zOFy;X!zMK`n8N#mwDrNhoVH6_h>rLfgk>=1TImXAP zRbdY=?GIQ@8MmN>W*0W8C>DgzPS4o4J_Vi``oNIwV8YCA(-AWU>+N9d5rcw z%idXd^sSvE01<|wwHD&s&lkxsBP)x&(xV_tVUuvR+5w7jmp#IcgbtJYcPms z{?N|E^wh@l871~TnVxYkgOeGhMfDNe@LJ7vcQ;K|)1Vy3>F~IGqKqlAahlRt1)UA$ zd-SlT3UBB9c9vJwSBhh3D?)nZJ`nPN@`c`^m-!>;+4H6a8WDr z&*!)Mnsygra&MIitwgg4uJMKJO~=qgU%+%}k$iD2T>_jr(;KS}F}UUeN2hENXs28>7WdFCv?M9V z{QB&s2t?d;==mXFILTk5#po%OuegYlO#Z|(=!HPGhVo?VimL``AzKvKl&wn*Mf5hC zHIsx2-On6IV#Ex`_d?RIEvk;pI_|{bjr}E)z{0QB+bs?OS7P3E(hrFrME5PTm9cO6 zq!l>ijkj&b)4la!JBNU8-QSN)$bS4yOa1|Hm3MFn{b300f*eZXEvG>_GVnxV+=rSo z_Jf<1&Ga#_nLuV{lx8=*VPMvG^@;fh3Q-Nio#g6p4Y8T&(J4CWjkY7?l8?Eb%)0b7 znf;9=J|ixwMo@3Lv4J~&gWwzzk^}_GXWV^DzXE*5jUNbGKAXYTW>70!B6}Lut3LMpbTqfMvVj1Kqby3gvJw%3FNn>keM|_4 zVsXqY1VS`iTjF&B?TbN0NBPAXHttu5(HMyTN1B;$xBbhKDSb2yyt5-6Lgziv!= z)B7edGKVFP8=yA0P3$pddS7-d+tjguil1jz6P*5v1Nmib8(nFffU3;y@5(;|@!^|U zB%b*K6BV&CCSPi3F+V&@erk5@oi}9t;>{u0RxJPY= z7Hb6c*Dub7SPxjgq`?O`lhbtt+PMol-vm{^i0B^>mD*>=H3Afl{o2fq)nyun8+a!f ze%MhZRL!A)a>cuB;Kj`VzO>k7F3;4o$22uYMnUg~8NsjWX%fakK`D`^%s<+Mm!soz ztg7@0YD@}eak(z#n6-Gfb-v})Oq|u~Mbin%c96(OsM})Zy3Zvv#J=6<}{^+*HF+2DLTCC~%TayPePqTsr=gb_xXER5jfCn8z)Ix`V~6Wa93hJi)q8?MY@g zF)a*sX+vF<7JbG`y0TufTx_(xanOFS44L6)H3pJ^&c*iaf$Au%C7YT_W{8F{39dby z6Jb;I!{W9T=f|l_JSEWY4gp2*yAw)YEL{y!H*Gj2zVX)?5ZZ+7Tx02osX&yaXp>EdHV}hMAq7!KziIE`3R8% z<$OKcR|zx@dZ|K7Lw<<9rGES0ToUo$aH#91L8tz37D1TuMcfCSm2#$2LE52z9F9ef zz!A!~7+(2F8Xz9!*4sc+2cVi?OHkm6hA#C=qLrttx=T`E7sNPt|G|tpf}FW0VJaS~ zz|ZUj0`W`{tvR#wpcK6z9-KTTce-S_)w@vahix3#N| z$GTI?iiFq>yIzn0nPiHn&0>Uftgy^g(qZgqzpW`eT-iS z0Jw4mmiX-!L>}l}Y-!o>mEhBGw8Z48WEgHbfoPmBlQp3-mw)Bk?XCC0dup!UA$CAs zl~9KdFr^ym>8ebjNTF^Szag;?CB1}a3;&C|_YP|^Yu`n2X6&Mah)5p+LHd9Oq<@YC zM4FI-^67W50hTPx7vJt@W;JUC;BZ`?>GIa&4^orj5tvDLg8>Bsw#5?>El)#;9WM z*y(NIrpFFtl!v6#uDm9)FQH&4%qt#-u7N^Vnu>`t5as2|-gahBdUo_qcGc#i?H6)y zWH;II&y?b#^ZIbHq?5m9EA?(;>{PDTkj3WO%ibW!yssUf`Y&uoZVzk0CisFw?P}eh zfb22=&%`3u7iG)m4R^h1@h3SX@eA{95!ZxducS|@4?k%yOE+}s&#BTY+X6W)gqfKm zVP?AEnw?}%`O`njNoj?#3#T(-HS+4rDTA^ z$Rtpb6#Mi*k9km>Fo+Dc=n2{W;q>2T&{4ah$PLVxnR?-;^)ziLD4_PI;*DHB5u3&2 zeh!Q71|qMU5B(CAP!>Eg+0!-~b^Jr(cHFoNw1h+scw=#gAHYzOoIs43CT0`6Gd9=n zI*^(1+H-K11OT2rw`Vom?Vc-Cp0kUbkyT|$`YF5~iXA=F-Rdmv$srpzY=ka>tsi!* z$1Z8(x@dfsh~j3j4gaP2SvXtf<$RJS>$Tc(2EtyrFO^_-RL3C&-?)%?P1m~{{Z49q!KVy2kt^o!7Dw3kz{;;i?AbSE5g~{R=Ox7C zx3;lkrX3s74opNA1!ft-TJrMA*6~ZiyW^`M`C1*s>hV$2k*vltl`v45X4n-h<2A;2M`3F4S(YUXX2@)q$NF}8ojQXikiMObalQ5|F@D7vLn+JO ztZszDNS-%CG!ZL>79OMZ>L|jtWWCs+mK?!DMKCzmkpx5Vmm#ngaf=mdMg|N``}bV( z%P^a%4$VVfaTa=V7u2=1Lb9oawpXh{UN$(CG?+v9gf`;0m^~rG!p#K?H~zwm&-ICK zk#ux*o8nW&o=Yk6o$QG+L&GsmSO`bf01R7s%{$igbnL>6az%q{%8x)%S-YD}Y26Wp zUc*TA=j4K&D8+9;e3n2nO*jWTg=g17tAw9lWB4mQ9kdf6CpEO0sB0s4n{%XW)f1uq z;$$Olnt-SyKBGskX26hUFo|EjSFV(-nmg04o#xEfUA{+R_1E5eSn0q}K`$gnT(;OB3DN&m=7LR!|;2T(Zt)LQ-)!mlKC=t`qna)}V z$jHw|n%JAT`Op}7Q;Zn0ZgchF^u3(bp2w3hRsjhP-AT4E_$07nRC#ds-s^hi_RL;j$C>u z#!@ZC5(VHW1sl^b8S$0bHNA$jz{X4IxvXfB2tGu}dh#!#G zKIca6W0HhbYM^<8PvwMh3;~lyp~EJ~-eW?hJU`s{!1H5XPTy`}nAh@p?RTERJdY-g z?>vD!hM9K9D?8n34$L> z2M4=%){W&EZyZ`AUN&qAPP^3y>SPcC*GP+p)W3Li(mi;1Mo^Rp<6_jU!ZO;WN4d|$ zR~BRKrte6IOg1Rk#~u$_axc@1Ws}OYfuwP(kd2+Zd$6#M`UKaWt-~c-_4n4pTDusa zj(TRoW+BE6H-wRD*mbC{nRS_U?)Jr`iykVu*Q)?M!Vzs6k~1Polz|08AV+CvjT~J& zjTXP0+ZdU$dcn`J~rl zy%EQ#{Vi`pqM8N!qVEdqve}P6^3LXU35|_ct$mKT5<@576a3m)B6xCh4|(fZ zu&+<;m)Y23)0PcfW>a^c_MsA_bBt#EgAjkc9ihdwWMA!|WR+W$cC&9TbbFuMN~Q8w z-zYcES`hzUdBEDqw>{+TX94EZ-mMV=GXh+MJUM{{U&T(K+^m|5ONNhIIXOMNw-1#b z_P|FbUB2@~f_`n)jsC1JFa-L}(|e>MkgZW$i>T0Vd+PMpkD+N= z4>*XJ43!d3$O&Jvc3OxA2k|1a9C!r%&hwJn%IZ;aPI%1pl{@dykjgW;wW0PsmJWvq2ji>BXoodbKp6ytw+C`bE~^q+z*?JU)MF1|jMFH)pZSPz-R^Im{n>(naRv>8FAIzS5yZ?gpika$;cz_kv zQP8M`7e@%3<_4)B^)GhlUr1omx-Htg%N+M)B6E71MTct|R2?1qRWkLxS?-%(a;g@4 z)~H6?58&tN@OL@hw5g!Y{F!Mx;*mAL{?7BqbHOBK{wzAl@^ije(IxH1%k|wd*bqMn* zy`|=cJ_}~j@qcaO7`YO4(Rd=mevIZ;a{Q<8F8H2`jeTpJFFOTjbDk z2H4DigYUW(D?9MRXLf+EwRTWBlo4xie(GS(SUZ4K6pp2C_iMSNKtT*!VMsUMVFOXFeKpI(2M%cGd!T5XaXtArCEM`G;<>LtmET7+fI2P z<%f##h2E`4=Ul_Qsk+ksHzUEQ{4J^ET*s>Cbmi_e<@r{lD;oAF)8DEL-Y31g67yv9 zS!uvGj11kULp6FyQv+s1vFvQJ#4_M!PaB6k1SRfWu5*JaaTj`+o4q=DRf9r&Tk4gV zrgy+zX|E5Rg{{Q&lLmnjKeFcO$U&E^Thy6i59YN^B`9rsL^bu>rPhRNS!PxF zhO_8|&PPYG==KMnuk$|dRH%={no>cl0yau!FL4 zt<|>EKk?TJcKbj_6@&7vNmezv35`iPS)7VsDS9ukzyv>FvV5mjAiOk1TlOW_$-xpq zTv>sC@~zjEx{Zncp_T$RJK%K~y0L8o!e4f$#eI1+)*bVx+V9kx>AiyfXQ4&y%h}KXs5)XDmi|}z}&5(J7&yv9Wnbh)98kvk0gablz6`y2%A)(Ri?3d zyP3$z5bKT~=|2S|x#$dmq`*u5lYP@P{&KT&!^-tgRaPcr(G3*va?b32l$Bi({%pbg zX0)UEgiWG(TsL#F*%d|nYy6%Wi4Ygdx?N_~-)^mavj$qEo$h)4){B)SLk=l~i0m&} zmc3nTW~V^9&8`WMlb8bPZ~Q+sh=|NKYQC2M7QKVFTJPg{qnK@T^^b!c5XGL;r3dnWQUSZ`1d ztvE}{z5&Pwh3P)&tMIx)wJW0R!@`xCbJt$c5cxoHs7*W6CXb9kl=awWT#w@h%iPD6<8lX*ScFYRf4;-7NTeadC77 zdpp`kuI?Fiyj&DIci`*z($Pm1L2UjqJO&!IEpjLbHw_GTyjpHXui=8&fGx_5+xyXB zPxpYc#(^U0B-hKJznoytigf$27)Yz1Q75Nj0~rtBuHX-^ot<%LLas&{xfRb1c`FpA zU05&Iq0+raMWDV$(2++t%O)3RemW*!!!?NRvqZ#Qumo!kn%jQf$lHFOnN#@}yB4X| zq&}K+W4PfoVHoZ{5|`u3+YS^}YI%rU^J|LxfwD3JTXLZFVFDh|zK+>!DgE%bVjk?9 zT_BaZ>hcKo^5UQ34D9Y?##f|ELLb&31n^p5MBhKMF*|dbWPcl}h98C4mF{0kJ6L*@E%~0g4jORX>mI+mP{*A|HqEl%dH#$netyoO1@>14jUYE6 z;$~Kr<mleR zuFQnKnX|t;Hu+7y{x&NZHXU0R58;dDe zFujipOv%{Y+Z)o!g70A(=VI{d?mvw;YV*v0aN;^vtpkK-!S>ijL-T z(~Ju}J~;PFVt)7x+1e{91;;0POf7ek&2#xh>FRuF6w~rUS#3`{ao&c){;NiWff zJ@y4`$j)i^7B;e!SBC+4pGdh{47$6RjvrLzt0-~Z5&Ii`{bulpXQ0ueg7PXz-%}r@ z2Z{P6-8nL2uFSTl; zon6XM;T{bV{ zO}Qj^hK5L(nC7!+BN6?E3N}N0Pi_-NAmU70@7R0|mySI6N7gsu(WM>8#;EK8kltBf z?;P=iuJj=@>g4ssZuInF>d`U>nX^@pDHzBv{@#&nE$eaIj@};MjR4sxZW9>smkZ9aocivkD3C&-@z0sDeEIu>5pJ0sx_zRuoqG&~f6c?&d}u zKUV`$|KjwMr1b!Sp0#duuIqfU8gEPB-PQ7oBLV{!hi92ocLH-)De_oS}wBQw{Y(&S?lJ;gNs+VU1KzN{N`kVeAIF*7s78|z2Ch2Q%4F7{U^s_^7ngE z;r#+nEMPSf6QV4UR(2|CY%>4iG_o!{F>;t#E{Wl~=^b;Sq}qszLE*dX*(t6o8V))8 ziO%x7C>c`r?RnRssWzW)eOuXi#=AISw%t62kl^Sn ziLFd@EBCjIX|?1Rf;M^mjh7QkHgL>;BTA zzd6YbB;xfKg}(;RLI#igxpP>ja^(Nt{v9aK^wWrDqDFWFdRNrS4BI_Q(}lI2l{P;b zo9J8$<4uDX(5iI%VN1!YROM-YqNjwj5Yp^5^7l?Zk>l{(Wz&W>7+CvVa#IL_37r=7 zDQ*(%cI?->7e@0A{Q9Fv{&1t)BkD8NXlJ0VpT#zMM1otjnBqcwYmwG0W&@wu?1RH> z;U_P#aWf?_8P8z1flauobIqp>jnG|4$V?;Y$Uyg8+e9tu&QS&-mOxDZNW6CRfYJE( z__mm8ahKvZmC$sBBInz0#HisQiJoiy(^`f0WQ(umo`ILH-Mwqw{m`2;c~4Hxb3D2A zC%!_z_K|fi1W;18G19-Y!9hd5Kcg!*BO~E0&*#5*&VI8LP=`)mdnfAf^rNzfgJns^ z>H3ZLuqKy!%TLoMQQagO)8IQ#CFV$Ab-aYKr+>BW+Bd!PUtN;9T#4hH{QtrqVi{`r zc=D6e+9&%l;+hy>Un?jj=NBzlZnt-%dVwG6f;WboCe)ZMqzyj?QY#yJX7XrGj!S?- zME+}yzUt+B!&$MD+xBi$njRzGw&1`%I@kJP7G-sV0$qDQPQO>YE9>iS*H5Nd?@~UT zs%hs5xvmp(m}2i#Jzo>jgY#l7CSI^{P?%~ayyI8p%Pv}evwOKwAIYx0?F4-QF^V75 zl<+Gz^h)H8qavX@OEK{%tb`U8T{)AuDHc&TGBgVcqNGip0Up-G+G;Y~%x7$+EzrV2 zzTM;?I+21b2~xBcQC9UNR5*`zhlV#N$B16rSvOQo*iF`N3Wa|2n?%I<-L=VHt_AMZ zct2Tk*V?@i3PX9l47W(#5Z3qPPqN!XUWpyw7KLyxTnj+Si0|E7^{<(-fy9%1jn+cK2$gg)cJv zrpDi!-S4U9a?e~giJWn-9W^LUTnPHs+qY}|u)l*6*0W}o?yBLtViIT={FD=iM9Q3p8|YkX<%fiS(}0E`49P`}g=+|q{Fuk(RM+!)Lo za9n-V&U3lw|Do>xC)dxBl|vrNiL-1;4_jRaQRCCpoRg)HE_j+uc{)zCv7cV9V2|N9 z4cLa=>m053kZm@GW2yD*-Ox4+X~Nh%HhLM5P1ZmQi3FLKp)mPA=}FWM{}SSmj@B?g z?Ph7GgJN;q;4~}esJP^q;`kXY)^$-y7{L~iw3eimftzE*YM}`t3N*fOHuNYOp`oDd zE;Da3mHYRoom6b?<2xlj=Y^$H+H^&qQq7u%460cejfje6*lyqQE7rNPBQ-Z$8MvP9 zbz@LFUQ5Ac4g6(m=mQzvJ*JV_NygMjPYVL7Au@;8qxtZdSDvLuhMt%I7_zb`nRsMJ zs8ctxv;vzc8L)M-{4q7^F#{m^bcHggZ~~cKX!NUI_bE9 zAI^WIyK3I(oR*F%J3tGZ0a-KJ>RKVZce1$m?&T7_v%K)mg#OCA9<~_Rz#FM^6evHRo9rN!>mdA01*b zT(_lNDuK*~YCc`-?B=HIuyhjF&W>?+TVdZdwUp7MJ+g%V#@?+tabRQ2 zP0`XJG%w<#$~iWd;8)ct8aMxxSNqnew?wOQ`THf|vM3v}AE-QBp#RXsL>sX%4ODdQ zU?ho92Wm#C@NE8s!({HqI0i@HSv?IX(iJ#;@+LnR$7f&MIU!k3mz3Wz{|x)Zr#-GT zM2UE?5v_e;1Z_`C+sTxF8z68c5)nK|M!P!Wn^*Z*D+|`-V@tD@Qy&zEuhcr@t3p2% z1M)6!YZe5qXB6T3Y;&#!UXBr6G%(!85E#YLS^JmAJv6R_pj-P@mGz0%2X#YVD*7DZ zw$N1~30F2z9^oufDZk^4m}!a<0YUa2F6Kp2TF8y81&PN=2j@>dxgu zKKx#9Jvssz9kr%rcG7aX6!M+S$7Br*Wma(z)+EKTvePL)E@^Uh_3MgQC; z;TT$o_uoC>&iu@Y8e}5Bkl|ID-?e3!t#ACitoE-LnDDu=_|RKxc6MfFPy2F9sb-HV zurXgrA?!lYP*U#SLf0+OQ?n`xILPy+Cev*89nIcASEah4AT(JS zZu+_Jj+w3NP7f-{?-;1N{*GatJGtpapg;G{lzsycrmec8g;xo2xEL-3l{^W886dL= zOUKiOiQrFnPoU1YggP3v!%Xgn-xYnh;-(1BxAsjPpF$%pIuVTIg^}K@g zx7ny0HpRpI1z-XVnta%m-y8;*=%FxK1J)kP8E@;ihO1#(+TMi=*R3w(%C`5z4U?d@ z0-B=JS=9V|nQ2IX{hW*w`xJb`6k~?G*{Y;Ugo8@hE`OU?P>Q1#l#VPnCN?DVIkWj z26@f1k~N3yLW678YC*rPJ7nws)VlMXM>Oi{r*8~x-TWK@ArsSnYoHvR-MrfGsE`dT zZk3d;K7Z|rjMrP0!GE2-KOG$4Lw3AeQoI55`#6#wo;cJ`vx1mxe%Lr5zqdd+mI5<; z4I#n@^%3;RVo{j~7wZ_b5;1<*V7SnN1GP5vl}Cd_3pY|S;zWGsd2H8ca({<-x}SW2 zi~ZXC;~U3@-N6g9mrK%HuoG8}_0smmM6jWj;UtK6jakZD&e@?nR~5Issq&Ld@7h6? z%Uo8?@!h-jd^N1$FhGsu^?IqI;4w$(KSQSOp6 zg|j4^ZYCEmPVjLVkSF*wR-#C*b98V;FQEhPyeA+){gyCTcDgdemJsv)L-7vOW^%_R zwuxgl#i{Qm!)7s4OjRKxXK7DG-Rp!{xs3iC`^xyLp68*9k3kH!M_XwAv!MHL>^+%j z-Os#-%;3?c})lAOQM=V z$94n4Bp4)MT4O844cKHC9E^d)kcD&ar%`20n^lILB}k{wiOgsVQ$f`?uo}rQ0~pM# zR?qNhPrmAEL3Q}A<;PdUo#50zR}zq{;%UJg*NvuK3O`YO<{J`|7ZfrVsakWV3gZ-5 z+$|eqYechP4~RD+wR7=~{xu(^t4H03U~nm|ErTU9VO>aXQYd6*Nm?<>amT6Z1=hBt z>Y@}mu+P@??v@RKdn}?Xih{^Oj@#s zbM1%%AY~&MK93EDD-2>C_HkIr=sM9kACXF=T~WZAg6l>XKMR!jXI408LqSE7n{$9J z(h2kcK1}A}bbXn*_7!{AAX!%k)HU6HIh6_Pb!!c(+`WSdi7QkCi;b>KG7OspG+v

AUR$p1PMe$*`cVx3$&410_zLaO77Iz7D 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 z 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 literal 0 HcmV?d00001 diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json index bbbb8c47..4de635e0 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -9,9 +9,10 @@ "acsConnectionString": "", "cognitiveServiceEndpoint": "", "callbackUriHost": "", + "textToPlayToLobbyUser": "You are currently in a lobby call, we will notify the admin that you are waiting.", "confirmMessageToTargetCall": "A user is waiting in lobby, do you want to add the lobby user to your call?", "acsGeneratedIdForLobbyCallReceiver": "", "acsGeneratedIdForTargetCallReceiver": "", "acsGeneratedIdForTargetCallSender": "", "socketToken": "" -} +} \ No newline at end of file diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md new file mode 100644 index 00000000..386c9d0b --- /dev/null +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -0,0 +1,78 @@ +| page_type | languages | products | +| --------- | --------------------------------------- | --------------------------------------------------------------------------- | +| sample |
DotNet
|
azureazure-communication-services
| + +# Call Automation - Lobby Call Support Sample + +In this sample, we cover how you can use Call Automation SDK to support Lobby Call where we join Lobby call users to a target call upon confirmation of admin in the target call. + +# Design + + +![Lobby Call Support](./Resources/Lobby_Call_Support_Scenario.jpg) + +## Prerequisites + +- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F). +- A deployed Communication Services resource. [Create a Communication Services resource](https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource). +- A [phone number](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number) in your Azure Communication Services resource that can make outbound calls. NB: phone numbers are not available in free subscriptions. +- Create Azure AI Multi Service resource. For details, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). +- Create and host a Azure Dev Tunnel. Instructions [here](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started) +- A Client application that can make calls to the Azure Communication Services resource. This can be a web client or a mobile client. You can use the [Web Client Quickstart](https://learn.microsoft.com/azure/communication-services/quickstarts/voice/csharp) + +## Before running the sample for the first time + +1. Open the web client app at `https:///` and sign in with your Azure Communication Services identity. +2. Clone the sample repository by running `git clone https://github.com/Azure-Samples/communication-services-python-quickstarts.git`. +3. Run the application and observe logs at console, keep this application running. + + ``` + npx webpack serve --config webpack.config.js + ``` + +### Setup and host your Azure DevTunnel + +[Azure DevTunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview) is an Azure service that enables you to share local web services hosted on the internet. Use the commands below to connect your local development environment to the public internet. This creates a tunnel with a persistent endpoint URL and which allows anonymous access. We will then use this endpoint to notify your application of calling events from the ACS Call Automation service. + +### Configuring application + +Open `main.py` file to configure the following settings + +1. `acsConnectionString`: Azure Communication Service resource's connection string. +2. `cognitiveServiceEndpoint`: Cognitive Service resource's endpoint. + - This is used to play media to the participants in the call. + - For more information, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). +3. `callbackUriHost`: Base url of the app. (For local development use dev tunnel url) +4. `confirmMessageToTargetCall`: Notification message to be played to the target call participants when they are moved from lobby call to target call. + - This is used to notify the target call participants that they are being moved from lobby call to target call. + - For more information, see [Play media in a call](https://learn.microsoft.com/en-us/azure/communication-services/concepts/calls/play-media). +5. `acsGeneratedIdForLobbyCallReceiver`: ACS Inbound Phone Number +6. `acsGeneratedIdForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time +7. `acsGeneratedIdForTargetCallSender`: ACS identity generated using web client +8. `socketToken`: ACS identity generated using web client + +## Run app locally + +1. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = , `. +2. Setup the following keys in the config/constants + ```"acsConnectionString": "", + "cognitiveServiceEndpoint": "", + "callbackUriHost": "", + "textToPlayToLobbyUser": "You are currently in a lobby call, we will notify the admin that you are waiting.", + "confirmMessageToTargetCall": "A user is waiting in lobby, do you want to add the lobby user to your call?", + "acsGeneratedIdForLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsGeneratedIdForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsGeneratedIdForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal) + "socketToken": ""(Token associated with in Azure Portal)``` +3. Define a websocket in your application(program.cs) to send and receive messages from and to client application(JS Hero App in this case). +4. Define a Client application that receives and responds to server notifications. Client application is available at . +5. Enter and validate user token in client app to send calls. +6. Start call to ``. +7. Expect Call Connected evennt in /callbacks +8. Start a call from ACS Test app(angular) to acsGeneratedIdForLobbyCallReceiver +9. Call will be answered and automated voice will be played to lobby user with the text ``. +10. Once the play completed, Target call will be notified with ``. +11. Once the Target call confirms from client application, Move `` in the backend sample. +12. If Target user says no, then no MOVE will be performed. +13. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. +14. Check `/Getparticipants` endpoint be called with Target call id, Target call must have the recent lobby user in the call. \ No newline at end of file From d13fb43c5d44b8a3c781b61576fd34208fc6a7bf Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Wed, 30 Jul 2025 21:42:05 +0530 Subject: [PATCH 05/27] Updates to Readme.md --- .../LobbyCallSupportSample/readme.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 386c9d0b..3d304617 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -18,12 +18,12 @@ In this sample, we cover how you can use Call Automation SDK to support Lobby Ca - A [phone number](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number) in your Azure Communication Services resource that can make outbound calls. NB: phone numbers are not available in free subscriptions. - Create Azure AI Multi Service resource. For details, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). - Create and host a Azure Dev Tunnel. Instructions [here](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started) -- A Client application that can make calls to the Azure Communication Services resource. This can be a web client or a mobile client. You can use the [Web Client Quickstart](https://learn.microsoft.com/azure/communication-services/quickstarts/voice/csharp) +- A Client application that can make calls to the Azure Communication Services resource. This can be a web client or a mobile client. You can use the [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample) ## Before running the sample for the first time -1. Open the web client app at `https:///` and sign in with your Azure Communication Services identity. -2. Clone the sample repository by running `git clone https://github.com/Azure-Samples/communication-services-python-quickstarts.git`. +1. Open the web client app at [JS Client Sample](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample) and sign in with your Azure Communication Services identity. +2. Clone the sample repository by running `git clone https://github.com/Azure-Samples/communication-services-javascript-quickstarts.git`. 3. Run the application and observe logs at console, keep this application running. ``` @@ -36,7 +36,7 @@ In this sample, we cover how you can use Call Automation SDK to support Lobby Ca ### Configuring application -Open `main.py` file to configure the following settings +Open `appSettings.json` file to configure the following settings 1. `acsConnectionString`: Azure Communication Service resource's connection string. 2. `cognitiveServiceEndpoint`: Cognitive Service resource's endpoint. @@ -46,10 +46,13 @@ Open `main.py` file to configure the following settings 4. `confirmMessageToTargetCall`: Notification message to be played to the target call participants when they are moved from lobby call to target call. - This is used to notify the target call participants that they are being moved from lobby call to target call. - For more information, see [Play media in a call](https://learn.microsoft.com/en-us/azure/communication-services/concepts/calls/play-media). -5. `acsGeneratedIdForLobbyCallReceiver`: ACS Inbound Phone Number -6. `acsGeneratedIdForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time -7. `acsGeneratedIdForTargetCallSender`: ACS identity generated using web client -8. `socketToken`: ACS identity generated using web client +5. `textToPlayToLobbyUser`: Text to be played to the lobby call user when they are waiting in the lobby. + - This is used to notify the lobby call user that they are waiting in the lobby. + - For more information, see [Play media in a call](https://learn.microsoft.com/en-us/azure/communication-services/concepts/calls/play-media). +6. `acsGeneratedIdForLobbyCallReceiver`: ACS Inbound Phone Number +7. `acsGeneratedIdForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time +8. `acsGeneratedIdForTargetCallSender`: ACS identity generated using web client +9. `socketToken`: ACS identity generated using web client ## Run app locally From 6f9786263906a155cc0f21f34c33b1132004aade Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Thu, 31 Jul 2025 13:46:38 +0530 Subject: [PATCH 06/27] Lobby Call Support Sample - removed token dependency for web socket communication. --- .../LobbyCallSupportSample/Program.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index d16113ad..6f35b76d 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -45,9 +45,6 @@ acsGeneratedIdForTargetCallSender = builder.Configuration["acsGeneratedIdForTargetCallSender"] ?? throw new ArgumentNullException("acsGeneratedIdForTargetCallSender"), - socketToken = - builder.Configuration["socketToken"] - ?? throw new ArgumentNullException("socketToken"), confirmMessageToTargetCall = builder.Configuration["confirmMessageToTargetCall"] ?? throw new ArgumentNullException("confirmMessageToTargetCall"), @@ -370,21 +367,14 @@ Playing Media to Lobby Call.. #region Websocket implementation app.UseWebSockets(); -app.Map($"/ws/{socketToken}", async context => +app.Map("/ws", async context => { - Console.WriteLine("Received WEB SOCKET request."); if (context.WebSockets.IsWebSocketRequest) { webSocket = await context.WebSockets.AcceptWebSocketAsync(); var buffer = new byte[1024 * 4]; - //// 1. Send message to JS - //var msg = "A user is waiting in lobby, do you want to add the user to your call?"; - //var bytes = Encoding.UTF8.GetBytes(msg); - //await webSocketFromContext.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text, true, CancellationToken.None); - - // 2. Receive client response // Keep alive with a read loop while (webSocket.State == WebSocketState.Open) { From f2091aa70f4d77897fd8c245aaa9fc0775610967 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Mon, 4 Aug 2025 12:44:05 +0530 Subject: [PATCH 07/27] Lobby Call Support Sample - moved missed sensitive data to config --- .../LobbyCallSupportSample/Program.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 6f35b76d..56e71d12 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -33,6 +33,9 @@ acsConnectionString = builder.Configuration["acsConnectionString"] ?? throw new ArgumentNullException("acsConnectionString"), + cognitiveServiceEndpoint = + builder.Configuration["cognitiveServiceEndpoint"] + ?? throw new ArgumentNullException("cognitiveServiceEndpoint"), callbackUriHost = builder.Configuration["callbackUriHost"] ?? throw new ArgumentNullException("callbackUriHost"), @@ -91,9 +94,9 @@ if (eventData is AcsIncomingCallEventData incomingCallEventData) { msgLog.AppendLine($"Event received: {eventGridEvent.EventType}"); - - string - fromCallerId = acsIdentity = incomingCallEventData.FromCommunicationIdentifier.RawId, + string + fromCallerId = + acsIdentity = incomingCallEventData.FromCommunicationIdentifier.RawId, toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; // Lobby Call: Answer @@ -106,7 +109,7 @@ OperationContext = !toCallerId.Contains(acsGeneratedIdForTargetCallReceiver) ? "LobbyCall" : "OtherCall", CallIntelligenceOptions = new CallIntelligenceOptions { - CognitiveServicesEndpoint = new Uri("https://cognitive-service-waferwire.cognitiveservices.azure.com/") + CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) } }; From cb981453162d43dc0acfaa699f59e46ff6e18f88 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Thu, 16 Oct 2025 22:09:24 +0530 Subject: [PATCH 08/27] Lobby Call feature - Readme.md updates and code tweaks --- .../LobbyCallSupportSample/Program.cs | 256 +++++++++--------- .../Properties/launchSettings.json | 20 +- .../Resources/client-app-ui.jpg | Bin 0 -> 18762 bytes .../LobbyCallSupportSample/appsettings.json | 17 +- .../LobbyCallSupportSample/readme.md | 52 ++-- 5 files changed, 163 insertions(+), 182 deletions(-) create mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/Resources/client-app-ui.jpg diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 56e71d12..b9c9e55a 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -48,12 +48,8 @@ acsGeneratedIdForTargetCallSender = builder.Configuration["acsGeneratedIdForTargetCallSender"] ?? throw new ArgumentNullException("acsGeneratedIdForTargetCallSender"), - confirmMessageToTargetCall = - builder.Configuration["confirmMessageToTargetCall"] - ?? throw new ArgumentNullException("confirmMessageToTargetCall"), - textToPlayToLobbyUser = - builder.Configuration["textToPlayToLobbyUser"] - ?? throw new ArgumentNullException("textToPlayToLobbyUser"), + confirmMessageToTargetCall = "A user is waiting in lobby, do you want to add the lobby user to your call?", + textToPlayToLobbyUser = "You are currently in a lobby call, we will notify the admin that you are waiting.", // Track which type of workflow call was last created lastWorkflowCallType = string.Empty, // "CallTwo" or "CallThree" acsIdentity = string.Empty, @@ -79,47 +75,50 @@ ~~~~~~~~~~~~ /api/LobbyCallSupportEventHandler ~~~~~~~~~~~~ """); - foreach (var eventGridEvent in eventGridEvents) + try { - if (eventGridEvent.TryGetSystemEventData(out object eventData)) + + foreach (var eventGridEvent in eventGridEvents) { - if (eventData is SubscriptionValidationEventData subscriptionValidationEventData) + if (eventGridEvent.TryGetSystemEventData(out object eventData)) { - var responseData = new SubscriptionValidationResponse + if (eventData is SubscriptionValidationEventData subscriptionValidationEventData) { - ValidationResponse = subscriptionValidationEventData.ValidationCode - }; - return Results.Ok(responseData); - } - if (eventData is AcsIncomingCallEventData incomingCallEventData) - { - msgLog.AppendLine($"Event received: {eventGridEvent.EventType}"); - string - fromCallerId = - acsIdentity = incomingCallEventData.FromCommunicationIdentifier.RawId, - toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; - - // Lobby Call: Answer - if (toCallerId.Contains(acsGeneratedIdForLobbyCallReceiver) || toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) + var responseData = new SubscriptionValidationResponse + { + ValidationResponse = subscriptionValidationEventData.ValidationCode + }; + return Results.Ok(responseData); + } + if (eventData is AcsIncomingCallEventData incomingCallEventData) { - #region Answer Call - Uri callbackUri = new (new Uri(callbackUriHost), $"/api/callbacks"); - AnswerCallOptions options = new (incomingCallEventData.IncomingCallContext, callbackUri) + msgLog.AppendLine($"Event received: {eventGridEvent.EventType}"); + string + fromCallerId = + acsIdentity = incomingCallEventData.FromCommunicationIdentifier.RawId, + toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; + + // Lobby Call: Answer + if (toCallerId.Contains(acsGeneratedIdForLobbyCallReceiver) || toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) { - OperationContext = !toCallerId.Contains(acsGeneratedIdForTargetCallReceiver) ? "LobbyCall" : "OtherCall", - CallIntelligenceOptions = new CallIntelligenceOptions + #region Answer Call + Uri callbackUri = new(new Uri(callbackUriHost), $"/api/callbacks"); + AnswerCallOptions options = new(incomingCallEventData.IncomingCallContext, callbackUri) { - CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) - } - }; + OperationContext = !toCallerId.Contains(acsGeneratedIdForTargetCallReceiver) ? "LobbyCall" : "OtherCall", + CallIntelligenceOptions = new CallIntelligenceOptions + { + CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) + } + }; - AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); - - if (toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) - { - targetCallConnectionId = answerCallResult.CallConnection.CallConnectionId; + AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); + + if (toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) + { + targetCallConnectionId = answerCallResult.CallConnection.CallConnectionId; - msgLog.AppendLine($""" + msgLog.AppendLine($""" Target Call(Inbound) Answered by Call Automation. From Caller Raw Id: {fromCallerId} To Caller Raw Id: {toCallerId} @@ -127,12 +126,12 @@ Target Call(Inbound) Answered by Call Automation. Correlation Id: {incomingCallEventData.CorrelationId} Target Call answered successfully. """); - } - else - { - lobbyConnectionId = answerCallResult.CallConnection.CallConnectionId; + } + else + { + lobbyConnectionId = answerCallResult.CallConnection.CallConnectionId; - msgLog.AppendLine($""" + msgLog.AppendLine($""" User Call(Inbound) Answered by Call Automation. From Caller Raw Id: {fromCallerId} To Caller Raw Id: {toCallerId} @@ -140,21 +139,26 @@ User Call(Inbound) Answered by Call Automation. Correlation Id: {incomingCallEventData.CorrelationId} Lobby Call answered successfully. """); + } + #endregion + } + else + { + //msgLog.AppendLine($"Call filtered out - not matching expected scenarios"); } - #endregion - } - else - { - //msgLog.AppendLine($"Call filtered out - not matching expected scenarios"); } } } + var logToSend = msgLog.ToString(); // avoiding multiple logs + msgLog.Clear(); + Console.WriteLine(logToSend); + return Results.Text(logToSend, "text/plain"); + } + catch (Exception ex) + { + Console.WriteLine($"Error occurred: {ex.Message}"); + return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); } - var logToSend = msgLog.ToString(); // avoiding multiple logs - msgLog.Clear(); - - Console.WriteLine(logToSend); - return Results.Text(logToSend, "text/plain"); }); #endregion @@ -164,114 +168,120 @@ Lobby Call answered successfully. app.MapPost("/api/callbacks", async (CloudEvent[] cloudEvents, ILogger logger) => { StringBuilder msgLog = new(); // to make string builder thread-safe; declared here - - foreach (var cloudEvent in cloudEvents) + try { - CallAutomationEventBase parsedEvent = CallAutomationEventParser.Parse(cloudEvent); - var callConnection = client.GetCallConnection(parsedEvent.CallConnectionId); - if (parsedEvent is CallConnected callConnected) + foreach (var cloudEvent in cloudEvents) { - Console.WriteLine($"~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ "); - Console.WriteLine($"Received callConnected.CallConnectionId : {callConnected.CallConnectionId}"); - if ((callConnected.OperationContext??string.Empty).Equals("LobbyCall", StringComparison.Ordinal)) + CallAutomationEventBase parsedEvent = CallAutomationEventParser.Parse(cloudEvent); + var callConnection = client.GetCallConnection(parsedEvent.CallConnectionId); + if (parsedEvent is CallConnected callConnected) { - // added logs to avoid multiple logs for the same callback - msgLog.AppendLine($""" + Console.WriteLine($"~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ "); + Console.WriteLine($"Received callConnected.CallConnectionId : {callConnected.CallConnectionId}"); + if ((callConnected.OperationContext ?? string.Empty).Equals("LobbyCall", StringComparison.Ordinal)) + { + // added logs to avoid multiple logs for the same callback + msgLog.AppendLine($""" ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ Received call event : {parsedEvent.GetType()} Lobby Call Connection Id: {callConnected.CallConnectionId} Correlation Id: {callConnected.CorrelationId} """); - // record lobby caller id and connection id - CallConnection lobbyCallConnection = client.GetCallConnection(callConnected.CallConnectionId); - CallConnectionProperties callConnectionProperties = lobbyCallConnection.GetCallConnectionProperties(); - lobbyCallerId = callConnectionProperties.Source.RawId; - lobbyConnectionId = callConnectionProperties.CallConnectionId; - Console.WriteLine($""" + // record lobby caller id and connection id + CallConnection lobbyCallConnection = client.GetCallConnection(callConnected.CallConnectionId); + CallConnectionProperties callConnectionProperties = lobbyCallConnection.GetCallConnectionProperties(); + lobbyCallerId = callConnectionProperties.Source.RawId; + lobbyConnectionId = callConnectionProperties.CallConnectionId; + Console.WriteLine($""" Lobby Caller Id: {lobbyCallerId} Lobby Connection Id: {lobbyConnectionId} """); - #region Play lobby waiting message - // setup cognitive service end point - Console.WriteLine($""" + #region Play lobby waiting message + // setup cognitive service end point + Console.WriteLine($""" Playing Media to Lobby Call.. """); - CallMedia callMedia = !string.IsNullOrEmpty(callConnected.CallConnectionId) ? - client.GetCallConnection(callConnected.CallConnectionId).GetCallMedia() - : throw new ArgumentNullException("Call connection id is empty"); - TextSource textSource = - new(textToPlayToLobbyUser) - { - VoiceName = "en-US-NancyNeural" - }; + CallMedia callMedia = !string.IsNullOrEmpty(callConnected.CallConnectionId) ? + client.GetCallConnection(callConnected.CallConnectionId).GetCallMedia() + : throw new ArgumentNullException("Call connection id is empty"); + TextSource textSource = + new(textToPlayToLobbyUser) + { + VoiceName = "en-US-NancyNeural" + }; - List playTo = - new() { new CommunicationUserIdentifier(acsIdentity) }; + List playTo = + new() { new CommunicationUserIdentifier(acsIdentity) }; - PlayOptions playToOptions = new(playSource: textSource, playTo: playTo) - { - OperationContext = "playToContext" - }; - await callMedia.PlayAsync(playToOptions); - #endregion + PlayOptions playToOptions = new(playSource: textSource, playTo: playTo) + { + OperationContext = "playToContext" + }; + await callMedia.PlayAsync(playToOptions); + #endregion + } } - } - else if (parsedEvent is PlayCompleted playCompleted) - { - // added logs to avoid multiple logs for the same callback - msgLog.AppendLine($""" + else if (parsedEvent is PlayCompleted playCompleted) + { + // added logs to avoid multiple logs for the same callback + msgLog.AppendLine($""" ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ Received event: {parsedEvent.GetType()} """); - // TODO: Notify Target Cal user - // By pop up in Client app - if (webSocket is null || webSocket.State != WebSocketState.Open) - { - msgLog.AppendLine("ERROR: Web socket is not available."); - return Results.NotFound("Message not sent"); - // throw new ArgumentNullException("web socket is not available."); - } + // TODO: Notify Target Cal user + // By pop up in Client app + if (webSocket is null || webSocket.State != WebSocketState.Open) + { + msgLog.AppendLine("ERROR: Web socket is not available."); + return Results.NotFound("Message not sent"); + // throw new ArgumentNullException("web socket is not available."); + } - // Notify Client - var msg = System.Text.Encoding.UTF8.GetBytes(confirmMessageToTargetCall); - await webSocket.SendAsync(new ArraySegment(msg), WebSocketMessageType.Text, true, CancellationToken.None); - msgLog.AppendLine($"Target Call notified with message: {confirmMessageToTargetCall}"); - return Results.Ok("Target Call notified with message: {confirmMessageToTargetCall}"); - } - else if (parsedEvent is MoveParticipantSucceeded moveParticipantSucceeded) - { - // added logs to avoid multiple logs for the same callback - msgLog.AppendLine($""" + // Notify Client + var msg = System.Text.Encoding.UTF8.GetBytes(confirmMessageToTargetCall); + await webSocket.SendAsync(new ArraySegment(msg), WebSocketMessageType.Text, true, CancellationToken.None); + msgLog.AppendLine($"Target Call notified with message: {confirmMessageToTargetCall}"); + return Results.Ok("Target Call notified with message: {confirmMessageToTargetCall}"); + } + else if (parsedEvent is MoveParticipantSucceeded moveParticipantSucceeded) + { + msgLog.AppendLine($""" ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ Received event: {parsedEvent.GetType()} Call Connection Id: {moveParticipantSucceeded.CallConnectionId} Correlation Id: {moveParticipantSucceeded.CorrelationId} """); - } - else if (parsedEvent is CallDisconnected callDisconnected) - { - // added logs to avoid multiple logs for the same callback - msgLog.AppendLine($""" + } + else if (parsedEvent is CallDisconnected callDisconnected) + { + // added logs to avoid multiple logs for the same callback + msgLog.AppendLine($""" ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ Received event: {parsedEvent.GetType()} Call Connection Id: {callDisconnected.CallConnectionId} """); + } + else + { + // msgLog.AppendLine($"Received event: {parsedEvent.GetType()}"); + } } - else + // Log the final message + if (0 != msgLog.Length) { - // msgLog.AppendLine($"Received event: {parsedEvent.GetType()}"); + Console.WriteLine(msgLog.ToString()); } + return Results.Text((0 == msgLog.Length) ? string.Empty : msgLog.ToString(), "text/plain"); } - // Log the final message - if (0 != msgLog.Length) + catch (Exception ex) { - Console.WriteLine(msgLog.ToString()); + Console.WriteLine($"Error occurred: {ex.Message}"); + return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); } - return Results.Text((0 == msgLog.Length) ? string.Empty : msgLog.ToString(), "text/plain"); }).Produces(StatusCodes.Status200OK); #endregion @@ -290,7 +300,7 @@ Playing Media to Lobby Call.. var createCallOptions = new CreateCallOptions(callInvite, callbackUri) { CallIntelligenceOptions = new CallIntelligenceOptions { - CognitiveServicesEndpoint = new Uri("https://cognitive-service-waferwire.cognitiveservices.azure.com/") + CognitiveServicesEndpoint = new Uri("") // Cognitive service URL }}; CreateCallResult createCallResult = await client.CreateCallAsync(createCallOptions); diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json index 688b8a42..9e23f2cf 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json @@ -8,17 +8,7 @@ "sslPort": 44389 } }, - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "launchUrl": "swagger", - "applicationUrl": "http://localhost:5142", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, + "profiles": { "https": { "commandName": "Project", "dotnetRunMessages": true, @@ -28,14 +18,6 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "swagger", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } } } } diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Resources/client-app-ui.jpg b/LobbyCallSupportSample/LobbyCallSupportSample/Resources/client-app-ui.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b461a337a1d0fb6fcaf65500e47baf38e0d68d6 GIT binary patch literal 18762 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 Script |
azureazure-communication-services
| +| sample |
DotNetC#
|
azureazure-communication-services
| # Call Automation - Lobby Call Support Sample -This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Callscenario. Users initially join a lobby call (Call - I) and remain on hold until an user in the target call (Call - II) confirms their participation. Once approved, the bot automatically moves the lobby user to the target call. +This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Call scenario. Users join a lobby call and remain on hold until an user in the target call confirms their participation. Once approved, Call Automation (bot) automatically connects the lobby users to the designated target call. +The sample uses a client application (java script sample) available in [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). # Design @@ -14,29 +15,32 @@ This sample demonstrates how to utilize the Call Automation SDK to implement a L ## Prerequisites - An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F). - A deployed Communication Services resource. [Create a Communication Services resource](https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource). -- A [phone number](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number) in your Azure Communication Services resource that can make outbound calls. NB: phone numbers are not available in free subscriptions. +- A [phone number](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number) in your Azure Communication Services resource that can make outbound calls. - Create Azure AI Multi Service resource. For details, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). - Create and host a Azure Dev Tunnel. Instructions [here](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started) -- A Client application that can make calls to the Azure Communication Services resource. This can be a web client or a mobile client. You can use the [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample) +- A Client application that can make calls to the Azure Communication Services resource. This can be a web client or a mobile client. You can use [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). ## Before running the sample for the first time -1. Open the web client app at [JS Client Sample](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample) and sign in with your Azure Communication Services identity. -2. Clone the sample repository by running `git clone https://github.com/Azure-Samples/communication-services-javascript-quickstarts.git`. -3. Run the application and observe logs at console, keep this application running. - - ``` - npx webpack serve --config webpack.config.js - ``` -4. UI of client application will be available at `http://localhost:/` and will look like below. - - ![Lobby Call Support](./Resources/client-app-ui.jpg) - +1. Open an instance of PowerShell, Windows Terminal, Command Prompt or equivalent and navigate to the directory that you would like to clone the sample to. +2. git clone https://github.com/Azure-Samples/Communication-Services-dotnet-quickstarts.git. +3. Navigate to `LobbyCallSupportSample` folder and open `LobbyCallSupportSample.sln` file. ### Setup and host your Azure DevTunnel [Azure DevTunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview) is an Azure service that enables you to share local web services hosted on the internet. Use the commands below to connect your local development environment to the public internet. This creates a tunnel with a persistent endpoint URL and which allows anonymous access. We will then use this endpoint to notify your application of calling events from the ACS Call Automation service. +``` + # Install the dev tunnel CLI tool + dotnet tool install -g Microsoft.DevTunnels.Client + # Authenticate with Azure + devtunnel login + # Create and start a new tunnel + devtunnel create --allow-anonymous + devtunnel port create -p 8080 + devtunnel host +``` + ### Configuring application Open `appSettings.json` file to configure the following settings @@ -64,14 +68,14 @@ Open `appSettings.json` file to configure the following settings "acsGeneratedIdForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) "acsGeneratedIdForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` 5. Define a websocket with url as `ws://your-websocket-server-url:port/ws` in your application(program.cs) to send and receive messages from and to the client application. -6. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at `http://localhost:/`. +6. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). 7. Start the target call in Client application, - Add token of target call sender(token would be generated in Azure user & tokens section). - Add user id of the target call receiver ``. - Click on `Start Call` button to initiate the call. 8. Expect Call Connected event in /callbacks as the server app answers incoming call from target call sender to target call receiver. -9. Start a call from ACS Test app(angular) to `acsGeneratedIdForLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` +9. Start a call from any Client Application (app used to make outbound calls) to `acsGeneratedIdForLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` 10. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. 11. Once the Target call confirms from client application, Move `ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER` in the backend sample. 12. If Target user says no, then no MOVE will be performed. From 208f0c31905cb63ec111868210382a00fc168406 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Thu, 23 Oct 2025 20:10:10 +0530 Subject: [PATCH 13/27] Lobby Support Sample - addressed comments in PR#80 from Python Quick starts --- .../LobbyCallSupportSample/Program.cs | 24 +++++++++---------- .../LobbyCallSupportSample/appsettings.json | 6 ++--- .../LobbyCallSupportSample/readme.md | 20 ++++++++-------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 8e13dad0..1061b022 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -39,15 +39,15 @@ callbackUriHost = builder.Configuration["callbackUriHost"] ?? throw new ArgumentNullException("callbackUriHost"), - acsGeneratedIdForLobbyCallReceiver = - builder.Configuration["acsGeneratedIdForLobbyCallReceiver"] - ?? throw new ArgumentNullException("acsGeneratedIdForLobbyCallReceiver"), - acsGeneratedIdForTargetCallReceiver = - builder.Configuration["acsGeneratedIdForTargetCallReceiver"] - ?? throw new ArgumentNullException("acsGeneratedIdForTargetCallReceiver"), - acsGeneratedIdForTargetCallSender = - builder.Configuration["acsGeneratedIdForTargetCallSender"] - ?? throw new ArgumentNullException("acsGeneratedIdForTargetCallSender"), + acsIdentityForLobbyCallReceiver = + builder.Configuration["acsIdentityForLobbyCallReceiver"] + ?? throw new ArgumentNullException("acsIdentityForLobbyCallReceiver"), + acsIdentityForTargetCallReceiver = + builder.Configuration["acsIdentityForTargetCallReceiver"] + ?? throw new ArgumentNullException("acsIdentityForTargetCallReceiver"), + acsIdentityForTargetCallSender = + builder.Configuration["acsIdentityForTargetCallSender"] + ?? throw new ArgumentNullException("acsIdentityForTargetCallSender"), confirmMessageToTargetCall = "A user is waiting in lobby, do you want to add the lobby user to your call?", textToPlayToLobbyUser = "You are currently in a lobby call, we will notify the admin that you are waiting.", // Track which type of workflow call was last created @@ -99,13 +99,13 @@ toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; // Lobby Call: Answer - if (toCallerId.Contains(acsGeneratedIdForLobbyCallReceiver) || toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) + if (toCallerId.Contains(acsIdentityForLobbyCallReceiver) || toCallerId.Contains(acsIdentityForTargetCallReceiver)) { #region Answer Call Uri callbackUri = new(new Uri(callbackUriHost), $"/api/callbacks"); AnswerCallOptions options = new(incomingCallEventData.IncomingCallContext, callbackUri) { - OperationContext = !toCallerId.Contains(acsGeneratedIdForTargetCallReceiver) ? "LobbyCall" : "OtherCall", + OperationContext = !toCallerId.Contains(acsIdentityForTargetCallReceiver) ? "LobbyCall" : "OtherCall", CallIntelligenceOptions = new CallIntelligenceOptions { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) @@ -114,7 +114,7 @@ AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); - if (toCallerId.Contains(acsGeneratedIdForTargetCallReceiver)) + if (toCallerId.Contains(acsIdentityForTargetCallReceiver)) { targetCallConnectionId = answerCallResult.CallConnection.CallConnectionId; diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json index 08bb8f52..b4b6ab00 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -9,7 +9,7 @@ "acsConnectionString": "ACS_CONNECTION_STRING", "cognitiveServiceEndpoint": "COGNITIVE_SERVICE_ENDPOINT", "callbackUriHost": "CALLBACK_URI_HOST", - "acsGeneratedIdForLobbyCallReceiver": "ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER", - "acsGeneratedIdForTargetCallReceiver": "ACS_GENERATED_ID_FOR_TARGET_CALL_RECEIVER", - "acsGeneratedIdForTargetCallSender": "ACS_GENERATED_ID_FOR_TARGET_CALL_SENDER" + "acsIdentityForLobbyCallReceiver": "ACS_IDENTITY_FOR_LOBBY_CALL_RECEIVER", + "acsIdentityForTargetCallReceiver": "ACS_IDENTITY_FOR_TARGET_CALL_RECEIVER", + "acsIdentityForTargetCallSender": "ACS_IDENTITY_FOR_TARGET_CALL_SENDER" } \ No newline at end of file diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index a0bc213b..e60a7053 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -50,13 +50,13 @@ Open `appSettings.json` file to configure the following settings - This is used to play media to the participants in the call. - For more information, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). 3. `callbackUriHost`: Base url of the app. (For local development use dev tunnel url) -4. `acsGeneratedIdForLobbyCallReceiver`: ACS Inbound Phone Number -5. `acsGeneratedIdForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time -6. `acsGeneratedIdForTargetCallSender`: ACS identity generated using web client +4. `acsIdentityForLobbyCallReceiver`: ACS Inbound Phone Number +5. `acsIdentityForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time +6. `acsIdentityForTargetCallSender`: ACS identity generated using web client ## Run app locally -1. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the Azure Portal(ACS Resource ? Identities & User Access Tokens ? Generate Identity and USER ACCESS TOKEN). +1. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the `Azure Portal(ACS Resource > Identities > User Access Tokens > Generate Identity and USER ACCESS TOKEN)`. 2. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = , `. 3. Setup webhook for Incoming calls to point to `https:///callbacks/incomingcall` in EventSubscription(Incoming). 4. Setup the following keys in the config/constants @@ -64,9 +64,9 @@ Open `appSettings.json` file to configure the following settings "acsConnectionString": "", "cognitiveServiceEndpoint": "", "callbackUriHost": "", - "acsGeneratedIdForLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsGeneratedIdForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsGeneratedIdForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` + "acsIdentityForLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsIdentityForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsIdentityForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` 5. Define a websocket with url as `ws://your-websocket-server-url:port/ws` in your application(program.cs) to send and receive messages from and to the client application. 6. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). @@ -75,9 +75,9 @@ Open `appSettings.json` file to configure the following settings - Add user id of the target call receiver ``. - Click on `Start Call` button to initiate the call. 8. Expect Call Connected event in /callbacks as the server app answers incoming call from target call sender to target call receiver. -9. Start a call from any Client Application (app used to make outbound calls) to `acsGeneratedIdForLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` +9. Start a call from any Client Application (app used to make outbound calls) to `acsIdentityForLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` 10. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. -11. Once the Target call confirms from client application, Move `ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER` in the backend sample. +11. Once the Target call confirms from client application, Move `acsIdentityForLobbyCallReceiver` in the backend sample. 12. If Target user says no, then no MOVE will be performed. 13. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. -14. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobbyy user(as lobby user is already moved into the target call). \ No newline at end of file +14. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobby user(as lobby user is already moved into the target call). \ No newline at end of file From 6091f972474c9bb4a8c907f5490ac40bf03f2aa6 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Fri, 24 Oct 2025 15:47:40 +0530 Subject: [PATCH 14/27] Lobby Support Sample - addressed comments in Python quick starts PR#80 --- .../LobbyCallSupportSample/Program.cs | 24 +++++++++---------- .../LobbyCallSupportSample/appsettings.json | 6 ++--- .../LobbyCallSupportSample/readme.md | 16 ++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 1061b022..71a6b258 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -39,15 +39,15 @@ callbackUriHost = builder.Configuration["callbackUriHost"] ?? throw new ArgumentNullException("callbackUriHost"), - acsIdentityForLobbyCallReceiver = - builder.Configuration["acsIdentityForLobbyCallReceiver"] - ?? throw new ArgumentNullException("acsIdentityForLobbyCallReceiver"), - acsIdentityForTargetCallReceiver = - builder.Configuration["acsIdentityForTargetCallReceiver"] - ?? throw new ArgumentNullException("acsIdentityForTargetCallReceiver"), - acsIdentityForTargetCallSender = - builder.Configuration["acsIdentityForTargetCallSender"] - ?? throw new ArgumentNullException("acsIdentityForTargetCallSender"), + acsLobbyCallReceiver = + builder.Configuration["acsLobbyCallReceiver"] + ?? throw new ArgumentNullException("acsLobbyCallReceiver"), + acsTargetCallReceiver = + builder.Configuration["acsTargetCallReceiver"] + ?? throw new ArgumentNullException("acsTargetCallReceiver"), + acsTargetCallSender = + builder.Configuration["acsTargetCallSender"] + ?? throw new ArgumentNullException("acsTargetCallSender"), confirmMessageToTargetCall = "A user is waiting in lobby, do you want to add the lobby user to your call?", textToPlayToLobbyUser = "You are currently in a lobby call, we will notify the admin that you are waiting.", // Track which type of workflow call was last created @@ -99,13 +99,13 @@ toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; // Lobby Call: Answer - if (toCallerId.Contains(acsIdentityForLobbyCallReceiver) || toCallerId.Contains(acsIdentityForTargetCallReceiver)) + if (toCallerId.Contains(acsLobbyCallReceiver) || toCallerId.Contains(acsTargetCallReceiver)) { #region Answer Call Uri callbackUri = new(new Uri(callbackUriHost), $"/api/callbacks"); AnswerCallOptions options = new(incomingCallEventData.IncomingCallContext, callbackUri) { - OperationContext = !toCallerId.Contains(acsIdentityForTargetCallReceiver) ? "LobbyCall" : "OtherCall", + OperationContext = !toCallerId.Contains(acsTargetCallReceiver) ? "LobbyCall" : "OtherCall", CallIntelligenceOptions = new CallIntelligenceOptions { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) @@ -114,7 +114,7 @@ AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); - if (toCallerId.Contains(acsIdentityForTargetCallReceiver)) + if (toCallerId.Contains(acsTargetCallReceiver)) { targetCallConnectionId = answerCallResult.CallConnection.CallConnectionId; diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json index b4b6ab00..6d3a6283 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -9,7 +9,7 @@ "acsConnectionString": "ACS_CONNECTION_STRING", "cognitiveServiceEndpoint": "COGNITIVE_SERVICE_ENDPOINT", "callbackUriHost": "CALLBACK_URI_HOST", - "acsIdentityForLobbyCallReceiver": "ACS_IDENTITY_FOR_LOBBY_CALL_RECEIVER", - "acsIdentityForTargetCallReceiver": "ACS_IDENTITY_FOR_TARGET_CALL_RECEIVER", - "acsIdentityForTargetCallSender": "ACS_IDENTITY_FOR_TARGET_CALL_SENDER" + "acsLobbyCallReceiver": "ACS_IDENTITY_FOR_LOBBY_CALL_RECEIVER", + "acsTargetCallReceiver": "ACS_IDENTITY_FOR_TARGET_CALL_RECEIVER", + "acsTargetCallSender": "ACS_IDENTITY_FOR_TARGET_CALL_SENDER" } \ No newline at end of file diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index e60a7053..bad078ca 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -50,9 +50,9 @@ Open `appSettings.json` file to configure the following settings - This is used to play media to the participants in the call. - For more information, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). 3. `callbackUriHost`: Base url of the app. (For local development use dev tunnel url) -4. `acsIdentityForLobbyCallReceiver`: ACS Inbound Phone Number -5. `acsIdentityForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time -6. `acsIdentityForTargetCallSender`: ACS identity generated using web client +4. `acsLobbyCallReceiver`: ACS Inbound Phone Number +5. `acsTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time +6. `acsTargetCallSender`: ACS identity generated using web client ## Run app locally @@ -64,9 +64,9 @@ Open `appSettings.json` file to configure the following settings "acsConnectionString": "", "cognitiveServiceEndpoint": "", "callbackUriHost": "", - "acsIdentityForLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsIdentityForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsIdentityForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` + "acsLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` 5. Define a websocket with url as `ws://your-websocket-server-url:port/ws` in your application(program.cs) to send and receive messages from and to the client application. 6. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). @@ -75,9 +75,9 @@ Open `appSettings.json` file to configure the following settings - Add user id of the target call receiver ``. - Click on `Start Call` button to initiate the call. 8. Expect Call Connected event in /callbacks as the server app answers incoming call from target call sender to target call receiver. -9. Start a call from any Client Application (app used to make outbound calls) to `acsIdentityForLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` +9. Start a call from any Client Application (app used to make outbound calls) to `acsLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` 10. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. -11. Once the Target call confirms from client application, Move `acsIdentityForLobbyCallReceiver` in the backend sample. +11. Once the Target call confirms from client application, Move `acsLobbyCallReceiver` in the backend sample. 12. If Target user says no, then no MOVE will be performed. 13. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. 14. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobby user(as lobby user is already moved into the target call). \ No newline at end of file From d17eed300f4083923ef6a0240846aa37b860d769 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Fri, 24 Oct 2025 17:07:56 +0530 Subject: [PATCH 15/27] Readme.md tweaks --- LobbyCallSupportSample/LobbyCallSupportSample/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index bad078ca..437c619a 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -72,7 +72,7 @@ Open `appSettings.json` file to configure the following settings 7. Start the target call in Client application, - Add token of target call sender(token would be generated in Azure user & tokens section). - - Add user id of the target call receiver ``. + - Add user id of the target call receiver `acsLobbyCallReceiver`. - Click on `Start Call` button to initiate the call. 8. Expect Call Connected event in /callbacks as the server app answers incoming call from target call sender to target call receiver. 9. Start a call from any Client Application (app used to make outbound calls) to `acsLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` From 4233a659c2159c119c5bcdfe2037145f4fcd8b47 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Sat, 25 Oct 2025 00:35:10 +0530 Subject: [PATCH 16/27] Lobby Call Sample - addressed PR Comments --- .../LobbyCallSupportSample/appsettings.json | 12 +++++----- .../LobbyCallSupportSample/readme.md | 22 +++++++++---------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json index 6d3a6283..0ecadf66 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -6,10 +6,10 @@ } }, "AllowedHosts": "*", - "acsConnectionString": "ACS_CONNECTION_STRING", - "cognitiveServiceEndpoint": "COGNITIVE_SERVICE_ENDPOINT", - "callbackUriHost": "CALLBACK_URI_HOST", - "acsLobbyCallReceiver": "ACS_IDENTITY_FOR_LOBBY_CALL_RECEIVER", - "acsTargetCallReceiver": "ACS_IDENTITY_FOR_TARGET_CALL_RECEIVER", - "acsTargetCallSender": "ACS_IDENTITY_FOR_TARGET_CALL_SENDER" + "acsConnectionString": "", + "cognitiveServiceEndpoint": "", + "callbackUriHost": "", + "acsLobbyCallReceiver": "", + "acsTargetCallReceiver": "", + "acsTargetCallSender": "" } \ No newline at end of file diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 437c619a..12b598db 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -36,7 +36,6 @@ The sample uses a client application (java script sample) available in [Web Clie # Authenticate with Azure devtunnel login # Create and start a new tunnel - devtunnel create --allow-anonymous devtunnel port create -p 8080 devtunnel host ``` @@ -56,25 +55,24 @@ Open `appSettings.json` file to configure the following settings ## Run app locally -1. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the `Azure Portal(ACS Resource > Identities > User Access Tokens > Generate Identity and USER ACCESS TOKEN)`. -2. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = , `. +1. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the `Azure Portal(ACS Resource > Identities > User Access Tokens > Generate Identity and User Access Token)`. +2. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = acsLobbyCallReceiver, acsTargetCallReceiver`. 3. Setup webhook for Incoming calls to point to `https:///callbacks/incomingcall` in EventSubscription(Incoming). 4. Setup the following keys in the config/constants - ``` - "acsConnectionString": "", - "cognitiveServiceEndpoint": "", - "callbackUriHost": "", - "acsLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` + ```"acsConnectionString": """", + "cognitiveServiceEndpoint": "", + "callbackUriHost": "", + "acsLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) + "acsTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` 5. Define a websocket with url as `ws://your-websocket-server-url:port/ws` in your application(program.cs) to send and receive messages from and to the client application. 6. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). 7. Start the target call in Client application, - Add token of target call sender(token would be generated in Azure user & tokens section). - - Add user id of the target call receiver `acsLobbyCallReceiver`. + - Add user id of the target call receiver `acsTargetCallReceiver`. - Click on `Start Call` button to initiate the call. -8. Expect Call Connected event in /callbacks as the server app answers incoming call from target call sender to target call receiver. +8. Expect `Call Connected` event in /callbacks as the server app answers incoming call from target call sender to target call receiver. 9. Start a call from any Client Application (app used to make outbound calls) to `acsLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` 10. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. 11. Once the Target call confirms from client application, Move `acsLobbyCallReceiver` in the backend sample. From 2ff15107b2dfec9750db9c78367c72d944a1ea2a Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Mon, 10 Nov 2025 23:05:50 +0530 Subject: [PATCH 17/27] Lobby Call Support Sample - Addresssing PR Review comments. --- .../LobbyCallSupportSample/Helper.cs | 100 ------------------ .../LobbyCallSupportSample/readme.md | 2 +- 2 files changed, 1 insertion(+), 101 deletions(-) delete mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs deleted file mode 100644 index 99f1a5bc..00000000 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Helper.cs +++ /dev/null @@ -1,100 +0,0 @@ -using Azure.Communication.CallAutomation; -using System.Net.WebSockets; -using System.Text; -using System.Text.Json; - -namespace LobbyCallSupportSample -{ - public static class Helper - { - 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 = StreamingData.Parse(msg); - - if (response != null) - { - if (response is AudioMetadata audioMetadata) - { - Console.WriteLine("***************************************************************************************"); - Console.WriteLine("MEDIA SUBSCRIPTION ID-->" + audioMetadata.MediaSubscriptionId); - Console.WriteLine("ENCODING-->" + audioMetadata.Encoding); - Console.WriteLine("SAMPLE RATE-->" + audioMetadata.SampleRate); - Console.WriteLine("CHANNELS-->" + audioMetadata.Channels); - //Console.WriteLine("LENGTH-->" + audioMetadata.Length); - Console.WriteLine("***************************************************************************************"); - } - if (response is AudioData audioData) - { - Console.WriteLine("***************************************************************************************"); - Console.WriteLine("DATA-->" + JsonSerializer.Serialize(audioData.Data)); - Console.WriteLine("TIMESTAMP-->" + audioData.Timestamp); - Console.WriteLine("IS SILENT-->" + audioData.IsSilent); - if (audioData.Participant != null && audioData.Participant.RawId != null) - { - Console.WriteLine("Participant Id-->" + audioData.Participant.RawId); - } - - Console.WriteLine("***************************************************************************************"); - } - - 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); - Console.WriteLine("DURATION-->" + transcriptionData.Duration); - 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); - Console.WriteLine("WORDS DURATION-->" + word.Duration); - } - 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/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 12b598db..21eb8480 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -36,7 +36,7 @@ The sample uses a client application (java script sample) available in [Web Clie # Authenticate with Azure devtunnel login # Create and start a new tunnel - devtunnel port create -p 8080 + devtunnel port create -p 7006 devtunnel host ``` From 7e441cf25c446cbace02a1bce6d328548c06354d Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Wed, 12 Nov 2025 19:37:59 +0530 Subject: [PATCH 18/27] Lobby Call Support Sample - Simplified programcs and readme.md --- .../LobbyCallSupportSample.csproj | 10 +- .../LobbyCallSupportSample/Program.cs | 602 +++++------------- .../LobbyCallSupportSample/readme.md | 217 +++++-- 3 files changed, 314 insertions(+), 515 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj b/LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj index 88be9e65..6b4baffb 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj +++ b/LobbyCallSupportSample/LobbyCallSupportSample/LobbyCallSupportSample.csproj @@ -7,14 +7,8 @@ - - - - - - - - + + diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 71a6b258..6ba5b491 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -7,522 +7,240 @@ using System.Net.WebSockets; using System.Text; -#region Bootstrap +// Bootstrap var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); - var app = builder.Build(); - -// Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } - app.UseHttpsRedirection(); -#endregion -#region Global Variables for LobbyCallSupportSample +// Config helper +string GetConfig(string key) => builder.Configuration[key] ?? throw new ArgumentNullException(key); +string acsConnectionString = GetConfig("acsConnectionString"), + cognitiveServiceEndpoint = GetConfig("cognitiveServiceEndpoint"), + callbackUriHost = GetConfig("callbackUriHost"), + acsLobbyCallReceiver = GetConfig("acsLobbyCallReceiver"), + acsTargetCallReceiver = GetConfig("acsTargetCallReceiver"), + acsTargetCallSender = GetConfig("acsTargetCallSender"); -string - // Configuration variables - acsConnectionString = - builder.Configuration["acsConnectionString"] - ?? throw new ArgumentNullException("acsConnectionString"), - cognitiveServiceEndpoint = - builder.Configuration["cognitiveServiceEndpoint"] - ?? throw new ArgumentNullException("cognitiveServiceEndpoint"), - callbackUriHost = - builder.Configuration["callbackUriHost"] - ?? throw new ArgumentNullException("callbackUriHost"), - acsLobbyCallReceiver = - builder.Configuration["acsLobbyCallReceiver"] - ?? throw new ArgumentNullException("acsLobbyCallReceiver"), - acsTargetCallReceiver = - builder.Configuration["acsTargetCallReceiver"] - ?? throw new ArgumentNullException("acsTargetCallReceiver"), - acsTargetCallSender = - builder.Configuration["acsTargetCallSender"] - ?? throw new ArgumentNullException("acsTargetCallSender"), - confirmMessageToTargetCall = "A user is waiting in lobby, do you want to add the lobby user to your call?", - textToPlayToLobbyUser = "You are currently in a lobby call, we will notify the admin that you are waiting.", - // Track which type of workflow call was last created - lastWorkflowCallType = string.Empty, // "CallTwo" or "CallThree" - acsIdentity = string.Empty, - // Call connection IDs - targetCallConnectionId = string.Empty, - lobbyConnectionId = string.Empty, // User's incoming call connection id - lobbyCallerId = string.Empty, // User's incoming caller id - callConnectionId2 = string.Empty; // ACS user's redirected call +const string confirmMsg = "A user is waiting in lobby, do you want to add the lobby user to your call?"; +const string lobbyMsg = "You are currently in a lobby call, we will notify the admin that you are waiting."; -// Web socket -WebSocket? webSocket = null; +string acsUserId = string.Empty, + targetConnId = string.Empty, + lobbyConnId = string.Empty, + lobbyUserId = string.Empty; -CallAutomationClient client = - new(connectionString: acsConnectionString); -#endregion +WebSocket? ws = null; +CallAutomationClient callClient = new(acsConnectionString); -#region Event Handler - -app.MapPost("/api/LobbyCallSupportEventHandler", async (EventGridEvent[] eventGridEvents, ILogger logger) => +// Event Handler +app.MapPost("/api/LobbyCallSupportEventHandler", async (EventGridEvent[] events, ILogger log) => { - StringBuilder msgLog = new(); // to make string builder thread-safe; declared here - msgLog.AppendLine(""" - - ~~~~~~~~~~~~ /api/LobbyCallSupportEventHandler ~~~~~~~~~~~~ - """); + log.LogInformation("~~~ /api/LobbyCallSupportEventHandler ~~~"); try { - - foreach (var eventGridEvent in eventGridEvents) + foreach (var e in events) { - if (eventGridEvent.TryGetSystemEventData(out object eventData)) + if (!e.TryGetSystemEventData(out var data)) continue; + switch (data) { - if (eventData is SubscriptionValidationEventData subscriptionValidationEventData) - { - var responseData = new SubscriptionValidationResponse + case SubscriptionValidationEventData s: + return Results.Ok(new SubscriptionValidationResponse { ValidationResponse = s.ValidationCode }); + case AcsIncomingCallEventData inc: + log.LogInformation("Event: {Type}", e.EventType); + acsUserId = inc.FromCommunicationIdentifier.RawId; + var toId = inc.ToCommunicationIdentifier.RawId; + if (toId.Contains(acsLobbyCallReceiver) || toId.Contains(acsTargetCallReceiver)) { - ValidationResponse = subscriptionValidationEventData.ValidationCode - }; - return Results.Ok(responseData); - } - if (eventData is AcsIncomingCallEventData incomingCallEventData) - { - msgLog.AppendLine($"Event received: {eventGridEvent.EventType}"); - string - fromCallerId = - acsIdentity = incomingCallEventData.FromCommunicationIdentifier.RawId, - toCallerId = incomingCallEventData.ToCommunicationIdentifier.RawId; - - // Lobby Call: Answer - if (toCallerId.Contains(acsLobbyCallReceiver) || toCallerId.Contains(acsTargetCallReceiver)) - { - #region Answer Call - Uri callbackUri = new(new Uri(callbackUriHost), $"/api/callbacks"); - AnswerCallOptions options = new(incomingCallEventData.IncomingCallContext, callbackUri) + var cbUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); + var opts = new AnswerCallOptions(inc.IncomingCallContext, cbUri) { - OperationContext = !toCallerId.Contains(acsTargetCallReceiver) ? "LobbyCall" : "OtherCall", - CallIntelligenceOptions = new CallIntelligenceOptions - { - CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) - } + OperationContext = !toId.Contains(acsTargetCallReceiver) ? "LobbyCall" : "OtherCall", + CallIntelligenceOptions = new() { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) } }; - - AnswerCallResult answerCallResult = await client.AnswerCallAsync(options); - - if (toCallerId.Contains(acsTargetCallReceiver)) + AnswerCallResult res = await callClient.AnswerCallAsync(opts); + if (toId.Contains(acsTargetCallReceiver)) { - targetCallConnectionId = answerCallResult.CallConnection.CallConnectionId; - - msgLog.AppendLine($""" - Target Call(Inbound) Answered by Call Automation. - From Caller Raw Id: {fromCallerId} - To Caller Raw Id: {toCallerId} - Target Call Connection Id: {targetCallConnectionId} - Correlation Id: {incomingCallEventData.CorrelationId} - Target Call answered successfully. - """); + targetConnId = res.CallConnection.CallConnectionId; + log.LogInformation("Target Call Answered. From: {From}, To: {To}, ConnId: {Conn}, CorrId: {Corr}", + acsUserId, toId, targetConnId, inc.CorrelationId); } else { - lobbyConnectionId = answerCallResult.CallConnection.CallConnectionId; - - msgLog.AppendLine($""" - User Call(Inbound) Answered by Call Automation. - From Caller Raw Id: {fromCallerId} - To Caller Raw Id: {toCallerId} - Lobby Call Connection Id: {lobbyConnectionId} - Correlation Id: {incomingCallEventData.CorrelationId} - Lobby Call answered successfully. - """); + lobbyConnId = res.CallConnection.CallConnectionId; + log.LogInformation("Lobby Call Answered. From: {From}, To: {To}, ConnId: {Conn}, CorrId: {Corr}", + acsUserId, toId, lobbyConnId, inc.CorrelationId); } - #endregion - } - else - { - //msgLog.AppendLine($"Call filtered out - not matching expected scenarios"); } - } + break; } } - var logToSend = msgLog.ToString(); // avoiding multiple logs - msgLog.Clear(); - Console.WriteLine(logToSend); - return Results.Text(logToSend, "text/plain"); + return Results.Ok(); } catch (Exception ex) { - Console.WriteLine($"Error occurred: {ex.Message}"); - return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); + log.LogError(ex, "Error"); + throw; } }); -#endregion - -#region Callback Handler - -app.MapPost("/api/callbacks", async (CloudEvent[] cloudEvents, ILogger logger) => +// Callback Handler +app.MapPost("/api/callbacks", async (CloudEvent[] events, ILogger log) => { - StringBuilder msgLog = new(); // to make string builder thread-safe; declared here try { - foreach (var cloudEvent in cloudEvents) + foreach (var ce in events) { - CallAutomationEventBase parsedEvent = CallAutomationEventParser.Parse(cloudEvent); - var callConnection = client.GetCallConnection(parsedEvent.CallConnectionId); - if (parsedEvent is CallConnected callConnected) + var ev = CallAutomationEventParser.Parse(ce); + var conn = callClient.GetCallConnection(ev.CallConnectionId); + switch (ev) { - Console.WriteLine($"~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ "); - Console.WriteLine($"Received callConnected.CallConnectionId : {callConnected.CallConnectionId}"); - if ((callConnected.OperationContext ?? string.Empty).Equals("LobbyCall", StringComparison.Ordinal)) - { - // added logs to avoid multiple logs for the same callback - msgLog.AppendLine($""" - ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ - Received call event : {parsedEvent.GetType()} - Lobby Call Connection Id: {callConnected.CallConnectionId} - Correlation Id: {callConnected.CorrelationId} - """); - - // record lobby caller id and connection id - CallConnection lobbyCallConnection = client.GetCallConnection(callConnected.CallConnectionId); - CallConnectionProperties callConnectionProperties = lobbyCallConnection.GetCallConnectionProperties(); - lobbyCallerId = callConnectionProperties.Source.RawId; - lobbyConnectionId = callConnectionProperties.CallConnectionId; - Console.WriteLine($""" - Lobby Caller Id: {lobbyCallerId} - Lobby Connection Id: {lobbyConnectionId} - """); - - #region Play lobby waiting message - // setup cognitive service end point - Console.WriteLine($""" - Playing Media to Lobby Call.. - """); - CallMedia callMedia = !string.IsNullOrEmpty(callConnected.CallConnectionId) ? - client.GetCallConnection(callConnected.CallConnectionId).GetCallMedia() - : throw new ArgumentNullException("Call connection id is empty"); - TextSource textSource = - new(textToPlayToLobbyUser) - { - VoiceName = "en-US-NancyNeural" - }; - - List playTo = - new() { new CommunicationUserIdentifier(acsIdentity) }; - - PlayOptions playToOptions = new(playSource: textSource, playTo: playTo) + case CallConnected cc when (cc.OperationContext ?? "") == "LobbyCall": + log.LogInformation("~~~ /api/callbacks ~~~\nCallConnected: {ConnId}", cc.CallConnectionId); + CallConnectionProperties props = conn.GetCallConnectionProperties(); + lobbyUserId = props.Source.RawId; + lobbyConnId = props.CallConnectionId; + log.LogInformation("Lobby Caller: {Caller}, Conn: {Conn}", lobbyUserId, lobbyConnId); + var media = callClient.GetCallConnection(cc.CallConnectionId).GetCallMedia(); + var textSrc = new TextSource(lobbyMsg) { VoiceName = "en-US-NancyNeural" }; + await media.PlayAsync(new PlayOptions(textSrc, [new CommunicationUserIdentifier(acsUserId)]) { OperationContext = "playToContext" }); + break; + case PlayCompleted: + log.LogInformation("PlayCompleted event"); + if (ws is null || ws.State != WebSocketState.Open) { - OperationContext = "playToContext" - }; - await callMedia.PlayAsync(playToOptions); - #endregion - } - } - else if (parsedEvent is PlayCompleted playCompleted) - { - // added logs to avoid multiple logs for the same callback - msgLog.AppendLine($""" - ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ - Received event: {parsedEvent.GetType()} - """); - - // TODO: Notify Target Cal user - // By pop up in Client app - if (webSocket is null || webSocket.State != WebSocketState.Open) - { - msgLog.AppendLine("ERROR: Web socket is not available."); - return Results.NotFound("Message not sent"); - // throw new ArgumentNullException("web socket is not available."); - } - - // Notify Client - var msg = System.Text.Encoding.UTF8.GetBytes(confirmMessageToTargetCall); - await webSocket.SendAsync(new ArraySegment(msg), WebSocketMessageType.Text, true, CancellationToken.None); - msgLog.AppendLine($"Target Call notified with message: {confirmMessageToTargetCall}"); - return Results.Ok("Target Call notified with message: {confirmMessageToTargetCall}"); - } - else if (parsedEvent is MoveParticipantSucceeded moveParticipantSucceeded) - { - msgLog.AppendLine($""" - ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ - Received event: {parsedEvent.GetType()} - Call Connection Id: {moveParticipantSucceeded.CallConnectionId} - Correlation Id: {moveParticipantSucceeded.CorrelationId} - """); - // move - // Get the updated participants list - msgLog.AppendLine($""" - - ~~~~~~~~~~~~ Participants in Target Connection({targetCallConnectionId}) ~~~~~~~~~~~~ - """); - try - { - CallConnection targetConnection = client.GetCallConnection(moveParticipantSucceeded.CallConnectionId); - var participants = await targetConnection.GetParticipantsAsync(); - - var participantinfo = participants.Value.Select(p => new - { - p.Identifier.RawId, - Type = p.Identifier.GetType().Name, - PhoneNumber = p.Identifier is PhoneNumberIdentifier phone ? phone.PhoneNumber : null, - AcsUserId = p.Identifier is CommunicationUserIdentifier user ? user.Id : null, - }).OrderBy(p => p.AcsUserId) // to display phone numbers first - .Select(p => new - { - Info = string.IsNullOrWhiteSpace(p.AcsUserId) - ? $"{p.Type} - RawId: {p.RawId}, Phone: {p.PhoneNumber}" // extra space for alignment - : $"{p.Type} - RawId: {p.AcsUserId}" - }); - - if (!participantinfo.Any()) - { - Console.WriteLine("No participants found for the specified call connection."); + log.LogError("WebSocket unavailable"); + return Results.NotFound("Message not sent"); } - else - { - msgLog.AppendLine($""" - No of Participants: {participantinfo.Count()} - Participants: - ------------- - {string.Join("\n", participantinfo.Select((p, index) => $"{index + 1}. {p.Info}"))} - """); - Console.WriteLine(msgLog.ToString()); - } - } - catch (Exception ex) - { - Console.WriteLine("Error getting participants for call {targetCallConnectionId}: {ex.Message}"); - - } - // end: Get the updated participants list - // end: move - } - else if (parsedEvent is CallDisconnected callDisconnected) - { - // added logs to avoid multiple logs for the same callback - msgLog.AppendLine($""" - ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ - Received event: {parsedEvent.GetType()} - Call Connection Id: {callDisconnected.CallConnectionId} - - """); - } - else - { - // msgLog.AppendLine($"Received event: {parsedEvent.GetType()}"); + await ws.SendAsync(Encoding.UTF8.GetBytes(confirmMsg), WebSocketMessageType.Text, true, CancellationToken.None); + log.LogInformation("Target notified: {Msg}", confirmMsg); + return Results.Ok($"Target notified: {confirmMsg}"); + case MoveParticipantSucceeded mps: + log.LogInformation("MoveParticipantSucceeded: {ConnId}", mps.CallConnectionId); + var tgtConn = callClient.GetCallConnection(mps.CallConnectionId); + var parts = await tgtConn.GetParticipantsAsync(); + LogParts(parts.Value, log); + break; + case CallDisconnected cd: + log.LogInformation("CallDisconnected: {ConnId}", cd.CallConnectionId); + break; } } - // Log the final message - if (0 != msgLog.Length) - { - Console.WriteLine(msgLog.ToString()); - } - return Results.Text((0 == msgLog.Length) ? string.Empty : msgLog.ToString(), "text/plain"); + return Results.Ok(); } catch (Exception ex) { - Console.WriteLine($"Error occurred: {ex.Message}"); - return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); + log.LogError(ex, "Error"); + throw; } -}).Produces(StatusCodes.Status200OK); - -#endregion +}).Produces(200); -#region Lobby Call Support Workflow Endpoints -app.MapPost("/TargetCallToAcsUser(Call Replaced with client app)", async (string acsTarget, ILogger logger) => +// Target Call Creation +app.MapPost("/TargetCallToAcsUser(Call Replaced with client app)", async (string tgt, ILogger log) => { - StringBuilder msgLog = new(); - msgLog.AppendLine(""" - - ~~~~~~~~~~~~ /TargetCall(Create) ~~~~~~~~~~~~ - """); - - Uri callbackUri = new(new Uri(callbackUriHost), "/api/callbacks"); - CallInvite callInvite = new(new CommunicationUserIdentifier(acsTarget)); - var createCallOptions = new CreateCallOptions(callInvite, callbackUri) { - CallIntelligenceOptions = new CallIntelligenceOptions - { - CognitiveServicesEndpoint = new Uri("") // Cognitive service URL - }}; - CreateCallResult createCallResult = await client.CreateCallAsync(createCallOptions); - - targetCallConnectionId = createCallResult.CallConnectionProperties.CallConnectionId; - - msgLog.Append($""" - TargetCall: - ----------- - From: Call Automation - To: {acsTarget} - Target Call Connection Id: {targetCallConnectionId} - Correlation Id: {createCallResult.CallConnectionProperties.CorrelationId} - """); - - Console.WriteLine(msgLog.ToString()); - return Results.Text(msgLog.ToString(), "text/plain"); + log.LogInformation("~~~ /TargetCall(Create) ~~~"); + var cbUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); + CreateCallResult res = await callClient.CreateCallAsync(new CreateCallOptions(new CallInvite(new CommunicationUserIdentifier(tgt)), cbUri) + { + CallIntelligenceOptions = new() { CognitiveServicesEndpoint = new Uri("") } + }); + targetConnId = res.CallConnectionProperties.CallConnectionId; + log.LogInformation("TargetCall: From: CallAutomation, To: {Tgt}, ConnId: {Conn}, CorrId: {Corr}", + tgt, targetConnId, res.CallConnectionProperties.CorrelationId); + return Results.Ok(); }).WithTags("Lobby Call Support APIs"); -app.MapGet("/GetParticipants/{callConnectionId}", async (string callConnectionId, ILogger logger) => -{ - StringBuilder msgLog = new(); - msgLog.AppendLine($""" - ~~~~~~~~~~~~ /GetParticipants/{callConnectionId} ~~~~~~~~~~~~ - """); +// Get Participants +app.MapGet("/GetParticipants/{connId}", async (string connId, ILogger log) => +{ + log.LogInformation("~~~ /GetParticipants/{ConnId} ~~~", connId); try { - var callConnection = client.GetCallConnection(callConnectionId); - var participants = await callConnection.GetParticipantsAsync(); - - var participantinfo = participants.Value.Select(p => new - { - p.Identifier.RawId, - Type = p.Identifier.GetType().Name, - PhoneNumber = p.Identifier is PhoneNumberIdentifier phone ? phone.PhoneNumber : null, - AcsUserId = p.Identifier is CommunicationUserIdentifier user ? user.Id : null, - }).OrderBy(p => p.AcsUserId) // to display phone numbers first - .Select(p => new - { - Info = string.IsNullOrWhiteSpace(p.AcsUserId) - ? $"{p.Type} - RawId: {p.RawId}, Phone: {p.PhoneNumber}" // extra space for alignment - : $"{p.Type} - RawId: {p.AcsUserId}" - }); - - if (!participantinfo.Any()) - { - return Results.NotFound(new - { - Message = "No participants found for the specified call connection.", - CallConnectionId = callConnectionId - }); - } - else - { - msgLog.AppendLine($""" - - No of Participants: {participantinfo.Count()} - Participants: - ------------- - {string.Join("\n", participantinfo.Select((p, index) => $"{index + 1}. {p.Info}"))} - """); - Console.WriteLine(msgLog.ToString()); - return Results.Text(msgLog.ToString(), "text/plain"); - } + var conn = callClient.GetCallConnection(connId); + var parts = await conn.GetParticipantsAsync(); + if (!parts.Value.Any()) + return Results.NotFound(new { Message = "No participants found.", CallConnectionId = connId }); + LogParts(parts.Value, log); + return Results.Ok(); } catch (Exception ex) { - logger.LogError($"Error getting participants for call {callConnectionId}: {ex.Message}"); - return Results.BadRequest(new - { - Error = ex.Message, - CallConnectionId = callConnectionId - }); + log.LogError("Error getting participants: {Msg}", ex.Message); + throw; } }).WithTags("Lobby Call Support APIs"); -#endregion - -#region Websocket implementation +// WebSocket app.UseWebSockets(); -app.Map("/ws", async context => +app.Map("/ws", async ctx => { - Console.WriteLine("Received WEB SOCKET request."); - if (context.WebSockets.IsWebSocketRequest) + var log = ctx.RequestServices.GetRequiredService>(); + log.LogInformation("WebSocket request"); + if (!ctx.WebSockets.IsWebSocketRequest) { - webSocket = await context.WebSockets.AcceptWebSocketAsync(); - var buffer = new byte[1024 * 4]; - - // Keep alive with a read loop - while (webSocket.State == WebSocketState.Open) + ctx.Response.StatusCode = 400; + return; + } + ws = await ctx.WebSockets.AcceptWebSocketAsync(); + var buf = new byte[4096]; + while (ws.State == WebSocketState.Open) + { + try { - try + var res = await ws.ReceiveAsync(new ArraySegment(buf), CancellationToken.None); + var msg = Encoding.UTF8.GetString(buf, 0, res.Count); + log.LogInformation("Client response: {Msg}", msg); + if (res.MessageType == WebSocketMessageType.Close) { - var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); - var jsResponse = Encoding.UTF8.GetString(buffer, 0, result.Count); - Console.WriteLine($"Received response from Client App: {jsResponse}"); - // Move participant to target call if response is "yes" - - if (result.MessageType == WebSocketMessageType.Close) + await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None); + } + else if (msg.Equals("yes", StringComparison.OrdinalIgnoreCase)) + { + log.LogInformation("Move Participant..."); + try { - Console.WriteLine($"result.MessageType: {result.MessageType}"); - await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None); + var tgtConn = callClient.GetCallConnection(targetConnId); + CommunicationIdentifier part = lobbyUserId.StartsWith("+") + ? new PhoneNumberIdentifier(lobbyUserId) + : new CommunicationUserIdentifier(lobbyUserId); + var moveRes = await tgtConn.MoveParticipantsAsync(new([part], lobbyConnId)); + var raw = moveRes.GetRawResponse(); + if (raw.Status is >= 200 and <= 299) + log.LogInformation("Move successful"); + else + throw new Exception($"Move failed: {raw.Status}"); } - else + catch (Exception ex) { - // Process incoming message or ignore - if (jsResponse.Equals("yes", StringComparison.OrdinalIgnoreCase)) - { - Console.WriteLine($"Move Participant operation begins.."); - // Call the Move Participants API - #region Move Participant - try - { - Console.WriteLine($""" - ~~~~~~~~~~~~ /api/callbacks ~~~~~~~~~~~~ - Move Participant operation started.. - Source Caller Id: {lobbyCallerId} - Source Connection Id: {lobbyConnectionId} - Target Connection Id: {targetCallConnectionId} - """); - - // Get the target connection - CallConnection targetConnection = client.GetCallConnection(targetCallConnectionId); - - // Get participants from source connection for reference - CallConnection sourceConnection = client.GetCallConnection(lobbyConnectionId); - - // Create participant identifier based on the input - CommunicationIdentifier participantToMove; - if (lobbyCallerId.StartsWith("+")) - { - // Phone number - participantToMove = new PhoneNumberIdentifier(lobbyCallerId); - } - else - { - // ACS Communication User - participantToMove = new CommunicationUserIdentifier(lobbyCallerId); - } - - var response = await targetConnection.MoveParticipantsAsync(options: new([participantToMove], lobbyConnectionId)); - var rawResponse = response.GetRawResponse(); - if (rawResponse.Status >= 200 && rawResponse.Status <= 299) - { - Console.WriteLine(); - Console.WriteLine("Move Participants operation completed successfully."); - } - else - { - throw new Exception($"Move Participants operation failed with status code: {rawResponse.Status}"); - } - } - catch (Exception ex) - { - Console.WriteLine($"Error in move participants operation: {ex.Message}"); - } - #endregion - - } + log.LogError("Move error: {Msg}", ex.Message); + throw; } - - } - catch (Exception ex) - { - Console.WriteLine("----- Web socket error -----"); - Console.WriteLine(ex.Message); - Console.WriteLine("----- End: Web socket error -----"); - } } - } - else - { - context.Response.StatusCode = 400; + catch (Exception ex) + { + log.LogError("WebSocket error: {Msg}", ex.Message); + throw; + } } }); -#endregion app.Run(); + +// Helper: Log participants +static void LogParts(IEnumerable parts, ILogger log) +{ + var info = parts.Select(p => p.Identifier switch + { + PhoneNumberIdentifier ph => $"Phone - RawId: {ph.RawId}, Phone: {ph.PhoneNumber}", + CommunicationUserIdentifier user => $"ACSUser - RawId: {user.Id}", + _ => $"{p.Identifier.GetType().Name} - RawId: {p.Identifier.RawId}" + }).ToList(); + log.LogInformation("Participants ({Count}):\n{List}", info.Count, string.Join("\n", info.Select((x, i) => $"{i + 1}. {x}"))); +} diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 21eb8480..d08ea1a2 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -1,81 +1,168 @@ -| page_type | languages | products | +| page_type | languages | products | | --------- | --------------------------------------- | --------------------------------------------------------------------------- | -| sample |
DotNetC#
|
azureazure-communication-services
| +| Sample |
DotNetC#
|
azureazure-communication-services
| -# Call Automation - Lobby Call Support Sample +# Call Automation – Lobby Call Support Sample -This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Call scenario. Users join a lobby call and remain on hold until an user in the target call confirms their participation. Once approved, Call Automation (bot) automatically connects the lobby users to the designated target call. -The sample uses a client application (java script sample) available in [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). +This sample demonstrates how to use the Call Automation SDK to implement a Lobby Call scenario with Azure Communication Services. Users join a lobby call and remain on hold until a participant in the target call confirms their participation. Once approved, the Call Automation bot automatically connects the lobby user to the designated target call. -# Design +--- +## Table of Contents +- [Overview](#overview) +- [Design](#design) +- [Prerequisites](#prerequisites) +- [Getting Started](#getting-started) +- [Configuration](#configuration) +- [Running the App Locally](#running-the-app-locally) +- [Workflow](#workflow) +- [Troubleshooting](#troubleshooting) + +--- + +## Overview + +This project provides a sample implementation for lobby call handling using Azure Communication Services and the Call Automation SDK. + +--- + +## Design ![Lobby Call Support](./Resources/Lobby_Call_Support_Scenario.jpg) +--- + ## Prerequisites -- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F). -- A deployed Communication Services resource. [Create a Communication Services resource](https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource). -- A [phone number](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number) in your Azure Communication Services resource that can make outbound calls. -- Create Azure AI Multi Service resource. For details, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). -- Create and host a Azure Dev Tunnel. Instructions [here](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started) -- A Client application that can make calls to the Azure Communication Services resource. This can be a web client or a mobile client. You can use [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). -## Before running the sample for the first time +- **Azure Account:** An Azure account with an active subscription. + https://azure.microsoft.com/free/?WT.mc_id=A261C142F. +- **Communication Services Resource:** A deployed Communication Services resource. + https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource. +- **Phone Number:** A https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number in your ACS resource that can make outbound calls. +- **Azure AI Multi-Service Resource:** + https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account. +- **Azure Dev Tunnel:** + https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started. +- **Client Application:** + Navigate to `LobbyCallSupport-Client` folder in https://github.com/Azure-Samples/communication-services-javascript-quickstarts. + +--- + +## Getting Started + +### Clone the Source Code + +1. Open PowerShell, Windows Terminal, Command Prompt, or equivalent. +2. Navigate to your desired directory. +3. Clone the repository: + ```sh + git clone https://github.com/Azure-Samples/Communication-Services-dotnet-quickstarts.git + +4. Open `LobbyCallSupportSample.sln` in Visual Studio. + +### Restore .NET Packages + +In the LobbyCallSupportSample directory, run: +```sh +dotnet restore +``` +--- -1. Open an instance of PowerShell, Windows Terminal, Command Prompt or equivalent and navigate to the directory that you would like to clone the sample to. -2. git clone https://github.com/Azure-Samples/Communication-Services-dotnet-quickstarts.git. -3. Navigate to `LobbyCallSupportSample` folder and open `LobbyCallSupportSample.sln` file. +## Setup and Host Azure Dev Tunnel -### Setup and host your Azure DevTunnel +``` +# Install Dev Tunnel CLI +dotnet tool install -g Microsoft.DevTunnels.Client -[Azure DevTunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview) is an Azure service that enables you to share local web services hosted on the internet. Use the commands below to connect your local development environment to the public internet. This creates a tunnel with a persistent endpoint URL and which allows anonymous access. We will then use this endpoint to notify your application of calling events from the ACS Call Automation service. +# Authenticate with Azure +devtunnel login +# Create and start a tunnel +devtunnel port create -p 7006 +devtunnel host start ``` - # Install the dev tunnel CLI tool - dotnet tool install -g Microsoft.DevTunnels.Client - # Authenticate with Azure - devtunnel login - # Create and start a new tunnel - devtunnel port create -p 7006 - devtunnel host +## Configuration + +Before running the application, configure the following settings in the `appSettings.json` file: + +| Setting | Description | Example Value | +|----------------------------|----------------------------------------------------------------------------------------------------------------|----------------------------------------------------| +| `acsConnectionString` | The connection string for your Azure Communication Services resource. Find this in the Azure Portal under your resource’s **Keys** section. | `"endpoint=https://.communication.azure.com/;accesskey="` | +| `cognitiveServiceEndpoint` | The endpoint for your Azure Cognitive Services resource. Used to play media to participants in the call. | `"https://"` | +| `callbackUriHost` | The base URL where your app will listen for incoming events from Azure Communication Services. For local development, use your Azure Dev Tunnel URL. | `"https://.devtunnels.ms"` | +| `acsLobbyCallReceiver` | ACS identity for the lobby call receiver. Generated using ACS SDK or Azure Portal. | `"8:acs:"` | +| `acsTargetCallReceiver` | ACS identity for the target call receiver. Generated using ACS SDK or Azure Portal. | `"8:acs:"` | +| `acsTargetCallSender` | ACS identity for the target call sender. Generated using ACS SDK or Azure Portal. | `"8:acs:"` | + +--- +### How to Obtain These Values + +- **acsConnectionString:** + 1. Go to the Azure Portal. + 2. Navigate to your Communication Services resource. + 3. Select **Keys & Connection String**. + 4. Copy the **Connection String** value. + +- **cognitiveServiceEndpoint:** + 1. Create an Azure AI Multi-Service resource. + 2. Copy the endpoint from the resource overview page. + +- **callbackUriHost:** + 1. Set up an Azure Dev Tunnel as described in the prerequisites. + 2. Use the public URL provided by the Dev Tunnel as your callback URI host. + +- **acsLobbyCallReceiver / acsTargetCallReceiver / acsTargetCallSender:** + 1. Use the ACS web client or SDK to generate user identities. + 2. Store the generated identity strings here. +#### Example `appSettings.json` + +```json +{ + "acsConnectionString": "endpoint=https://.communication.azure.com/;accesskey=", + "cognitiveServiceEndpoint": "https://", + "callbackUriHost": "https://.devtunnels.ms", + "acsLobbyCallReceiver": "8:acs:", + "acsTargetCallReceiver": "8:acs:", + "acsTargetCallSender": "8:acs:" +} ``` - -### Configuring application - -Open `appSettings.json` file to configure the following settings - -1. `acsConnectionString`: Azure Communication Service resource's connection string. -2. `cognitiveServiceEndpoint`: Cognitive Service resource's endpoint. - - This is used to play media to the participants in the call. - - For more information, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). -3. `callbackUriHost`: Base url of the app. (For local development use dev tunnel url) -4. `acsLobbyCallReceiver`: ACS Inbound Phone Number -5. `acsTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time -6. `acsTargetCallSender`: ACS identity generated using web client - -## Run app locally - -1. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the `Azure Portal(ACS Resource > Identities > User Access Tokens > Generate Identity and User Access Token)`. -2. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = acsLobbyCallReceiver, acsTargetCallReceiver`. -3. Setup webhook for Incoming calls to point to `https:///callbacks/incomingcall` in EventSubscription(Incoming). -4. Setup the following keys in the config/constants - ```"acsConnectionString": """", - "cognitiveServiceEndpoint": "", - "callbackUriHost": "", - "acsLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` -5. Define a websocket with url as `ws://your-websocket-server-url:port/ws` in your application(program.cs) to send and receive messages from and to the client application. -6. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at [Web Client Quickstart](https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample). - -7. Start the target call in Client application, - - Add token of target call sender(token would be generated in Azure user & tokens section). - - Add user id of the target call receiver `acsTargetCallReceiver`. - - Click on `Start Call` button to initiate the call. -8. Expect `Call Connected` event in /callbacks as the server app answers incoming call from target call sender to target call receiver. -9. Start a call from any Client Application (app used to make outbound calls) to `acsLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` -10. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. -11. Once the Target call confirms from client application, Move `acsLobbyCallReceiver` in the backend sample. -12. If Target user says no, then no MOVE will be performed. -13. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. -14. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobby user(as lobby user is already moved into the target call). \ No newline at end of file +--- +## Running the App Locally + +1. **Generate ACS identities** for lobby and target participants in **Azure Portal**. +2. **Setup EventSubscription** for incoming calls: + - Filter: `TO.DATA.RAWID = acsLobbyCallReceiver, acsTargetCallReceiver`. +3. **Configure webhook** for incoming calls: + `https:///callbacks/incomingcall` +4. Define a **WebSocket** in `program.cs` for client-server communication. +5. Use the **JS Client App** from https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample. + +--- +## Workflow + +- Start target call in client app: + - Add token for `acsTargetCallSender`. + - Add user ID for `acsTargetCallReceiver`. + - Click **Start Call**. +- Incoming call from target sender → server answers → `Call Connected` event. +- Lobby user calls `acsLobbyCallReceiver` → automated voice plays: `You are currently in a lobby call, we will notify the admin that you are waiting.` +- Target call receives notification: `A user is waiting in lobby, do you want to add them to your call?` +- If confirmed → **MoveParticipantSucceeded** event → lobby user joins target call. +- If declined → no move is performed. + +--- +## Troubleshooting + +### Common Issues +- **Invalid ACS Connection String:** + Verify `acsConnectionString` in `appSettings.json`. +- **Callback URL Not Reachable:** + Ensure Dev Tunnel is running and URL matches `callbackUriHost`. +- **Phone Number Issues:** + Confirm numbers are provisioned and in E.164 format. +- **Identity Errors:** + Regenerate ACS identities if invalid. + +For more help: +- https://learn.microsoft.com/azure/communication-services/ +- https://learn.microsoft.com/answers/topics/azure-communication-services.html \ No newline at end of file From 80fbd85365ed5282a6fa8231109007760128a16e Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Wed, 12 Nov 2025 19:43:29 +0530 Subject: [PATCH 19/27] Lobby Call Support Sample - readme.md tweaks --- LobbyCallSupportSample/LobbyCallSupportSample/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index d08ea1a2..c41e2f3e 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -135,7 +135,7 @@ Before running the application, configure the following settings in the `appSett 3. **Configure webhook** for incoming calls: `https:///callbacks/incomingcall` 4. Define a **WebSocket** in `program.cs` for client-server communication. -5. Use the **JS Client App** from https://github.com/Azure-Samples/communication-services-javascript-quickstarts/tree/users/v-kuppu/LobbyCallConfirmSample. +5. Use the **JS Client App**, Navigate to `LobbyCallSupport-Client` folder in https://github.com/Azure-Samples/communication-services-javascript-quickstarts. --- ## Workflow From 7031e00ce6d5be9f6db7f8b5978722a69d5d52af Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Thu, 13 Nov 2025 17:06:30 +0530 Subject: [PATCH 20/27] Lobby Call Support Sample - Simplified program.cs and readme.md --- .../LobbyCallSupportSample/Program.cs | 3 +-- .../Properties/launchSettings.json | 12 ++---------- .../LobbyCallSupportSample/readme.md | 17 +++++++++-------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 6ba5b491..55f4216b 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -181,7 +181,7 @@ app.Map("/ws", async ctx => { var log = ctx.RequestServices.GetRequiredService>(); - log.LogInformation("WebSocket request"); + // log.LogInformation("WebSocket request"); if (!ctx.WebSockets.IsWebSocketRequest) { ctx.Response.StatusCode = 400; @@ -226,7 +226,6 @@ catch (Exception ex) { log.LogError("WebSocket error: {Msg}", ex.Message); - throw; } } }); diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json index 9e23f2cf..d114625f 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json @@ -1,20 +1,12 @@ { - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:39947", - "sslPort": 44389 - } - }, + "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { "https": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:7006;http://localhost:5142", + "applicationUrl": "https://localhost:7006", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index c41e2f3e..a3c2e74e 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -140,15 +140,15 @@ Before running the application, configure the following settings in the `appSett --- ## Workflow -- Start target call in client app: +- Start target call in client app `LobbyCallSupport-Client`: - Add token for `acsTargetCallSender`. - Add user ID for `acsTargetCallReceiver`. - Click **Start Call**. -- Incoming call from target sender → server answers → `Call Connected` event. +- Incoming call from target sender → server answers → expect `Call Connected` event. - Lobby user calls `acsLobbyCallReceiver` → automated voice plays: `You are currently in a lobby call, we will notify the admin that you are waiting.` -- Target call receives notification: `A user is waiting in lobby, do you want to add them to your call?` -- If confirmed → **MoveParticipantSucceeded** event → lobby user joins target call. -- If declined → no move is performed. +- Target call receives notification (a confirm dialog): `A user is waiting in lobby, do you want to add them to your call?` +- If confirmed → expect **MoveParticipantSucceeded** event → lobby user joins target call. +- If Target user declined → lobby user will not be moved to target call. --- ## Troubleshooting @@ -163,6 +163,7 @@ Before running the application, configure the following settings in the `appSett - **Identity Errors:** Regenerate ACS identities if invalid. -For more help: -- https://learn.microsoft.com/azure/communication-services/ -- https://learn.microsoft.com/answers/topics/azure-communication-services.html \ No newline at end of file +**Still having trouble?** +- Review the official https://learn.microsoft.com/azure/communication-services/. +- Search for similar issues or ask questions on https://learn.microsoft.com/answers/topics/azure-communication-services.html. +- Contact your Azure administrator or support team if you suspect a permissions or resource issue. \ No newline at end of file From 54b43d4b25a7031cefc66f653106221adc70bb81 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Fri, 14 Nov 2025 15:15:30 +0530 Subject: [PATCH 21/27] Lobby Call Support Sample - Made code more readable. --- .../LobbyCallSupportSample/Program.cs | 284 ++++++++++-------- 1 file changed, 164 insertions(+), 120 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 55f4216b..e7eff370 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -7,75 +7,87 @@ using System.Net.WebSockets; using System.Text; -// Bootstrap var builder = WebApplication.CreateBuilder(args); + builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); + var app = builder.Build(); + if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } + app.UseHttpsRedirection(); -// Config helper -string GetConfig(string key) => builder.Configuration[key] ?? throw new ArgumentNullException(key); -string acsConnectionString = GetConfig("acsConnectionString"), - cognitiveServiceEndpoint = GetConfig("cognitiveServiceEndpoint"), - callbackUriHost = GetConfig("callbackUriHost"), - acsLobbyCallReceiver = GetConfig("acsLobbyCallReceiver"), - acsTargetCallReceiver = GetConfig("acsTargetCallReceiver"), - acsTargetCallSender = GetConfig("acsTargetCallSender"); +// Configuration helper +string GetConfig(string key) => builder.Configuration[key] ?? throw new ArgumentNullException(paramName: key); + +string acsConnectionString = GetConfig(key: "acsConnectionString"), + cognitiveServiceEndpoint = GetConfig(key: "cognitiveServiceEndpoint"), + callbackUriHost = GetConfig(key: "callbackUriHost"), + acsLobbyCallReceiver = GetConfig(key: "acsLobbyCallReceiver"), + acsTargetCallReceiver = GetConfig(key: "acsTargetCallReceiver"), + acsTargetCallSender = GetConfig(key: "acsTargetCallSender"); -const string confirmMsg = "A user is waiting in lobby, do you want to add the lobby user to your call?"; -const string lobbyMsg = "You are currently in a lobby call, we will notify the admin that you are waiting."; +const string confirmationMessage = "A user is waiting in lobby, do you want to add the lobby user to your call?"; +const string lobbyMessage = "You are currently in a lobby call, we will notify the admin that you are waiting."; string acsUserId = string.Empty, - targetConnId = string.Empty, - lobbyConnId = string.Empty, + targetCallConnectionId = string.Empty, + lobbyCallConnectionId = string.Empty, lobbyUserId = string.Empty; -WebSocket? ws = null; -CallAutomationClient callClient = new(acsConnectionString); +WebSocket? webSocket = null; +CallAutomationClient callAutomationClient = new(connectionString: acsConnectionString); // Event Handler -app.MapPost("/api/LobbyCallSupportEventHandler", async (EventGridEvent[] events, ILogger log) => +app.MapPost("/api/LobbyCallSupportEventHandler", async (EventGridEvent[] events, ILogger logger) => { - log.LogInformation("~~~ /api/LobbyCallSupportEventHandler ~~~"); + logger.LogInformation("~~~ /api/LobbyCallSupportEventHandler ~~~"); try { - foreach (var e in events) + foreach (var eventGridEvent in events) { - if (!e.TryGetSystemEventData(out var data)) continue; - switch (data) + if (!eventGridEvent.TryGetSystemEventData(out var eventData)) continue; + switch (eventData) { - case SubscriptionValidationEventData s: - return Results.Ok(new SubscriptionValidationResponse { ValidationResponse = s.ValidationCode }); - case AcsIncomingCallEventData inc: - log.LogInformation("Event: {Type}", e.EventType); - acsUserId = inc.FromCommunicationIdentifier.RawId; - var toId = inc.ToCommunicationIdentifier.RawId; - if (toId.Contains(acsLobbyCallReceiver) || toId.Contains(acsTargetCallReceiver)) + case SubscriptionValidationEventData validationEvent: + return Results.Ok(value: new SubscriptionValidationResponse { ValidationResponse = validationEvent.ValidationCode }); + + case AcsIncomingCallEventData incomingCallEvent: + logger.LogInformation("Event: {Type}", eventGridEvent.EventType); + acsUserId = incomingCallEvent.FromCommunicationIdentifier.RawId; + var toIdentifier = incomingCallEvent.ToCommunicationIdentifier.RawId; + if (toIdentifier.Contains(acsLobbyCallReceiver) || toIdentifier.Contains(acsTargetCallReceiver)) { - var cbUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); - var opts = new AnswerCallOptions(inc.IncomingCallContext, cbUri) + var callbackUri = new Uri(baseUri: new Uri(callbackUriHost), relativeUri: "/api/callbacks"); + var answerCallOptions = new AnswerCallOptions( + incomingCallContext: incomingCallEvent.IncomingCallContext, + callbackUri: callbackUri) { - OperationContext = !toId.Contains(acsTargetCallReceiver) ? "LobbyCall" : "OtherCall", - CallIntelligenceOptions = new() { CognitiveServicesEndpoint = new Uri(cognitiveServiceEndpoint) } + OperationContext = !toIdentifier.Contains(acsTargetCallReceiver) ? "LobbyCall" : "OtherCall", + CallIntelligenceOptions = new CallIntelligenceOptions + { + CognitiveServicesEndpoint = new Uri(uriString: cognitiveServiceEndpoint) + } }; - AnswerCallResult res = await callClient.AnswerCallAsync(opts); - if (toId.Contains(acsTargetCallReceiver)) + AnswerCallResult answerResult = await callAutomationClient.AnswerCallAsync(options: answerCallOptions); + if (toIdentifier.Contains(acsTargetCallReceiver)) { - targetConnId = res.CallConnection.CallConnectionId; - log.LogInformation("Target Call Answered. From: {From}, To: {To}, ConnId: {Conn}, CorrId: {Corr}", - acsUserId, toId, targetConnId, inc.CorrelationId); + targetCallConnectionId = answerResult.CallConnection.CallConnectionId; + logger.LogInformation( + "Target Call Answered. From: {From}, To: {To}, ConnId: {Conn}, CorrId: {Corr}", + acsUserId, toIdentifier, targetCallConnectionId, incomingCallEvent.CorrelationId); } else { - lobbyConnId = res.CallConnection.CallConnectionId; - log.LogInformation("Lobby Call Answered. From: {From}, To: {To}, ConnId: {Conn}, CorrId: {Corr}", - acsUserId, toId, lobbyConnId, inc.CorrelationId); + lobbyCallConnectionId = answerResult.CallConnection.CallConnectionId; + logger.LogInformation( + "Lobby Call Answered. From: {From}, To: {To}, ConnId: {Conn}, CorrId: {Corr}", + acsUserId, toIdentifier, lobbyCallConnectionId, incomingCallEvent.CorrelationId); } } break; @@ -85,50 +97,63 @@ } catch (Exception ex) { - log.LogError(ex, "Error"); + logger.LogError(exception: ex, message: "Error"); throw; } }); // Callback Handler -app.MapPost("/api/callbacks", async (CloudEvent[] events, ILogger log) => +app.MapPost("/api/callbacks", async (CloudEvent[] events, ILogger logger) => { try { - foreach (var ce in events) + foreach (var cloudEvent in events) { - var ev = CallAutomationEventParser.Parse(ce); - var conn = callClient.GetCallConnection(ev.CallConnectionId); - switch (ev) + var callEvent = CallAutomationEventParser.Parse(cloudEvent); + var callConnection = callAutomationClient.GetCallConnection(callConnectionId: callEvent.CallConnectionId); + switch (callEvent) { - case CallConnected cc when (cc.OperationContext ?? "") == "LobbyCall": - log.LogInformation("~~~ /api/callbacks ~~~\nCallConnected: {ConnId}", cc.CallConnectionId); - CallConnectionProperties props = conn.GetCallConnectionProperties(); - lobbyUserId = props.Source.RawId; - lobbyConnId = props.CallConnectionId; - log.LogInformation("Lobby Caller: {Caller}, Conn: {Conn}", lobbyUserId, lobbyConnId); - var media = callClient.GetCallConnection(cc.CallConnectionId).GetCallMedia(); - var textSrc = new TextSource(lobbyMsg) { VoiceName = "en-US-NancyNeural" }; - await media.PlayAsync(new PlayOptions(textSrc, [new CommunicationUserIdentifier(acsUserId)]) { OperationContext = "playToContext" }); + case CallConnected callConnected when (callConnected.OperationContext ?? "") == "LobbyCall": + logger.LogInformation("~~~ /api/callbacks ~~~\nCallConnected: {ConnId}", callConnected.CallConnectionId); + CallConnectionProperties callProperties = callConnection.GetCallConnectionProperties(); + lobbyUserId = callProperties.Source.RawId; + lobbyCallConnectionId = callProperties.CallConnectionId; + logger.LogInformation("Lobby Caller: {Caller}, Conn: {Conn}", lobbyUserId, lobbyCallConnectionId); + var callMedia = callAutomationClient.GetCallConnection(callConnected.CallConnectionId).GetCallMedia(); + var textSource = new TextSource(text: lobbyMessage) { VoiceName = "en-US-NancyNeural" }; + await callMedia.PlayAsync( + options: new PlayOptions( + playSource: textSource, + playTo: [new CommunicationUserIdentifier(id: acsUserId)]) + { + OperationContext = "playToContext" + }); break; + case PlayCompleted: - log.LogInformation("PlayCompleted event"); - if (ws is null || ws.State != WebSocketState.Open) + logger.LogInformation("PlayCompleted event"); + if (webSocket is null || webSocket.State != WebSocketState.Open) { - log.LogError("WebSocket unavailable"); - return Results.NotFound("Message not sent"); + logger.LogError("WebSocket unavailable"); + return Results.NotFound(value: "Message not sent"); } - await ws.SendAsync(Encoding.UTF8.GetBytes(confirmMsg), WebSocketMessageType.Text, true, CancellationToken.None); - log.LogInformation("Target notified: {Msg}", confirmMsg); - return Results.Ok($"Target notified: {confirmMsg}"); - case MoveParticipantSucceeded mps: - log.LogInformation("MoveParticipantSucceeded: {ConnId}", mps.CallConnectionId); - var tgtConn = callClient.GetCallConnection(mps.CallConnectionId); - var parts = await tgtConn.GetParticipantsAsync(); - LogParts(parts.Value, log); + await webSocket.SendAsync( + buffer: Encoding.UTF8.GetBytes(confirmationMessage), + messageType: WebSocketMessageType.Text, + endOfMessage: true, + cancellationToken: CancellationToken.None); + logger.LogInformation("Target notified: {Msg}", confirmationMessage); + return Results.Ok(value: $"Target notified: {confirmationMessage}"); + + case MoveParticipantSucceeded moveParticipantSucceeded: + logger.LogInformation("MoveParticipantSucceeded: {ConnId}", moveParticipantSucceeded.CallConnectionId); + var targetConnection = callAutomationClient.GetCallConnection(callConnectionId: moveParticipantSucceeded.CallConnectionId); + var participants = await targetConnection.GetParticipantsAsync(); + LogParticipants(participants: participants.Value, logger: logger); break; - case CallDisconnected cd: - log.LogInformation("CallDisconnected: {ConnId}", cd.CallConnectionId); + + case CallDisconnected callDisconnected: + logger.LogInformation("CallDisconnected: {ConnId}", callDisconnected.CallConnectionId); break; } } @@ -136,96 +161,111 @@ } catch (Exception ex) { - log.LogError(ex, "Error"); + logger.LogError(exception: ex, message: "Error"); throw; } -}).Produces(200); +}).Produces(statusCode: 200); // Target Call Creation -app.MapPost("/TargetCallToAcsUser(Call Replaced with client app)", async (string tgt, ILogger log) => +app.MapPost("/TargetCallToAcsUser(Call Replaced with client app)", async (string targetUserId, ILogger logger) => { - log.LogInformation("~~~ /TargetCall(Create) ~~~"); - var cbUri = new Uri(new Uri(callbackUriHost), "/api/callbacks"); - CreateCallResult res = await callClient.CreateCallAsync(new CreateCallOptions(new CallInvite(new CommunicationUserIdentifier(tgt)), cbUri) - { - CallIntelligenceOptions = new() { CognitiveServicesEndpoint = new Uri("") } - }); - targetConnId = res.CallConnectionProperties.CallConnectionId; - log.LogInformation("TargetCall: From: CallAutomation, To: {Tgt}, ConnId: {Conn}, CorrId: {Corr}", - tgt, targetConnId, res.CallConnectionProperties.CorrelationId); + logger.LogInformation("~~~ /TargetCall(Create) ~~~"); + var callbackUri = new Uri(baseUri: new Uri(callbackUriHost), relativeUri: "/api/callbacks"); + CreateCallResult createCallResult = await callAutomationClient.CreateCallAsync( + options: new CreateCallOptions( + callInvite: new CallInvite(targetIdentity: new CommunicationUserIdentifier(id: targetUserId)), + callbackUri: callbackUri) + { + CallIntelligenceOptions = new CallIntelligenceOptions + { + CognitiveServicesEndpoint = new Uri(uriString: "") + } + }); + targetCallConnectionId = createCallResult.CallConnectionProperties.CallConnectionId; + logger.LogInformation( + "TargetCall: From: CallAutomation, To: {Tgt}, ConnId: {Conn}, CorrId: {Corr}", + targetUserId, targetCallConnectionId, createCallResult.CallConnectionProperties.CorrelationId); return Results.Ok(); }).WithTags("Lobby Call Support APIs"); // Get Participants -app.MapGet("/GetParticipants/{connId}", async (string connId, ILogger log) => +app.MapGet("/GetParticipants/{connId}", async (string connId, ILogger logger) => { - log.LogInformation("~~~ /GetParticipants/{ConnId} ~~~", connId); + logger.LogInformation("~~~ /GetParticipants/{ConnId} ~~~", connId); try { - var conn = callClient.GetCallConnection(connId); - var parts = await conn.GetParticipantsAsync(); - if (!parts.Value.Any()) - return Results.NotFound(new { Message = "No participants found.", CallConnectionId = connId }); - LogParts(parts.Value, log); + var callConnection = callAutomationClient.GetCallConnection(callConnectionId: connId); + var participants = await callConnection.GetParticipantsAsync(); + if (!participants.Value.Any()) + return Results.NotFound(value: new { Message = "No participants found.", CallConnectionId = connId }); + LogParticipants(participants: participants.Value, logger: logger); return Results.Ok(); } catch (Exception ex) { - log.LogError("Error getting participants: {Msg}", ex.Message); + logger.LogError("Error getting participants: {Msg}", ex.Message); throw; } }).WithTags("Lobby Call Support APIs"); // WebSocket app.UseWebSockets(); -app.Map("/ws", async ctx => +app.Map("/ws", async context => { - var log = ctx.RequestServices.GetRequiredService>(); - // log.LogInformation("WebSocket request"); - if (!ctx.WebSockets.IsWebSocketRequest) + var logger = context.RequestServices.GetRequiredService>(); + if (!context.WebSockets.IsWebSocketRequest) { - ctx.Response.StatusCode = 400; + context.Response.StatusCode = 400; return; } - ws = await ctx.WebSockets.AcceptWebSocketAsync(); - var buf = new byte[4096]; - while (ws.State == WebSocketState.Open) + webSocket = await context.WebSockets.AcceptWebSocketAsync(); + var buffer = new byte[4096]; + while (webSocket.State == WebSocketState.Open) { try { - var res = await ws.ReceiveAsync(new ArraySegment(buf), CancellationToken.None); - var msg = Encoding.UTF8.GetString(buf, 0, res.Count); - log.LogInformation("Client response: {Msg}", msg); - if (res.MessageType == WebSocketMessageType.Close) + var receiveResult = await webSocket.ReceiveAsync( + buffer: new ArraySegment(buffer), + cancellationToken: CancellationToken.None); + var clientMessage = Encoding.UTF8.GetString(buffer, 0, receiveResult.Count); + logger.LogInformation("Client response: {Msg}", clientMessage); + + if (receiveResult.MessageType == WebSocketMessageType.Close) { - await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None); + await webSocket.CloseAsync( + closeStatus: WebSocketCloseStatus.NormalClosure, + statusDescription: "Closing", + cancellationToken: CancellationToken.None); } - else if (msg.Equals("yes", StringComparison.OrdinalIgnoreCase)) + else if (clientMessage.Equals("yes", StringComparison.OrdinalIgnoreCase)) { - log.LogInformation("Move Participant..."); + logger.LogInformation("Move Participant..."); try { - var tgtConn = callClient.GetCallConnection(targetConnId); - CommunicationIdentifier part = lobbyUserId.StartsWith("+") - ? new PhoneNumberIdentifier(lobbyUserId) - : new CommunicationUserIdentifier(lobbyUserId); - var moveRes = await tgtConn.MoveParticipantsAsync(new([part], lobbyConnId)); - var raw = moveRes.GetRawResponse(); - if (raw.Status is >= 200 and <= 299) - log.LogInformation("Move successful"); + var targetConnection = callAutomationClient.GetCallConnection(callConnectionId: targetCallConnectionId); + CommunicationIdentifier participant = lobbyUserId.StartsWith("+") + ? new PhoneNumberIdentifier(phoneNumber: lobbyUserId) + : new CommunicationUserIdentifier(id: lobbyUserId); + var moveResult = await targetConnection.MoveParticipantsAsync( + options: new MoveParticipantsOptions( + targetParticipants: [participant], + fromCall: lobbyCallConnectionId)); + var rawResponse = moveResult.GetRawResponse(); + if (rawResponse.Status is >= 200 and <= 299) + logger.LogInformation("Move successful"); else - throw new Exception($"Move failed: {raw.Status}"); + throw new Exception(message: $"Move failed: {rawResponse.Status}"); } catch (Exception ex) { - log.LogError("Move error: {Msg}", ex.Message); + logger.LogError("Move error: {Msg}", ex.Message); throw; } } } catch (Exception ex) { - log.LogError("WebSocket error: {Msg}", ex.Message); + logger.LogError("WebSocket error: {Msg}", ex.Message); } } }); @@ -233,13 +273,17 @@ app.Run(); // Helper: Log participants -static void LogParts(IEnumerable parts, ILogger log) +static void LogParticipants(IEnumerable participants, ILogger logger) { - var info = parts.Select(p => p.Identifier switch + var participantInfo = participants.Select(participant => participant.Identifier switch { - PhoneNumberIdentifier ph => $"Phone - RawId: {ph.RawId}, Phone: {ph.PhoneNumber}", + PhoneNumberIdentifier phone => $"Phone - RawId: {phone.RawId}, Phone: {phone.PhoneNumber}", CommunicationUserIdentifier user => $"ACSUser - RawId: {user.Id}", - _ => $"{p.Identifier.GetType().Name} - RawId: {p.Identifier.RawId}" + _ => $"{participant.Identifier.GetType().Name} - RawId: {participant.Identifier.RawId}" }).ToList(); - log.LogInformation("Participants ({Count}):\n{List}", info.Count, string.Join("\n", info.Select((x, i) => $"{i + 1}. {x}"))); -} + + logger.LogInformation( + "Participants ({Count}):\n{List}", + participantInfo.Count, + string.Join("\n", participantInfo.Select((info, index) => $"{index + 1}. {info}"))); +} \ No newline at end of file From 40083c41b8c5e65410a6402990254a64f1bb4277 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Fri, 14 Nov 2025 16:52:29 +0530 Subject: [PATCH 22/27] Lobby Call Support Sample - readme.md file updates --- .../LobbyCallSupportSample/readme.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index a3c2e74e..e30312bf 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -131,11 +131,11 @@ Before running the application, configure the following settings in the `appSett 1. **Generate ACS identities** for lobby and target participants in **Azure Portal**. 2. **Setup EventSubscription** for incoming calls: - - Filter: `TO.DATA.RAWID = acsLobbyCallReceiver, acsTargetCallReceiver`. -3. **Configure webhook** for incoming calls: - `https:///callbacks/incomingcall` -4. Define a **WebSocket** in `program.cs` for client-server communication. -5. Use the **JS Client App**, Navigate to `LobbyCallSupport-Client` folder in https://github.com/Azure-Samples/communication-services-javascript-quickstarts. + - Set up a Web hook(`https:///callbacks/incomingcall`) for callback. + - Add Filter: + - Key: `data.to.rawid`, operator: `string contains`, value: `acsLobbyCallReceiver, acsTargetCallReceiver` +3. Define a **WebSocket** in `program.cs` for client-server communication. +4. Use the **JS Client App**, Navigate to `LobbyCallSupport-Client` folder in https://github.com/Azure-Samples/communication-services-javascript-quickstarts. --- ## Workflow From f1c6648947d6b7c91e8e340586cba628deb0702d Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Tue, 18 Nov 2025 14:01:13 +0530 Subject: [PATCH 23/27] Lobby Call Support Sample - removed extra config variables --- .../LobbyCallSupportSample/Program.cs | 25 +------------------ .../Properties/launchSettings.json | 4 +-- .../LobbyCallSupportSample/appsettings.json | 3 +-- .../LobbyCallSupportSample/readme.md | 8 +++--- 4 files changed, 9 insertions(+), 31 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index e7eff370..09a5b5b9 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -29,8 +29,7 @@ cognitiveServiceEndpoint = GetConfig(key: "cognitiveServiceEndpoint"), callbackUriHost = GetConfig(key: "callbackUriHost"), acsLobbyCallReceiver = GetConfig(key: "acsLobbyCallReceiver"), - acsTargetCallReceiver = GetConfig(key: "acsTargetCallReceiver"), - acsTargetCallSender = GetConfig(key: "acsTargetCallSender"); + acsTargetCallReceiver = GetConfig(key: "acsTargetCallReceiver"); const string confirmationMessage = "A user is waiting in lobby, do you want to add the lobby user to your call?"; const string lobbyMessage = "You are currently in a lobby call, we will notify the admin that you are waiting."; @@ -166,28 +165,6 @@ await webSocket.SendAsync( } }).Produces(statusCode: 200); -// Target Call Creation -app.MapPost("/TargetCallToAcsUser(Call Replaced with client app)", async (string targetUserId, ILogger logger) => -{ - logger.LogInformation("~~~ /TargetCall(Create) ~~~"); - var callbackUri = new Uri(baseUri: new Uri(callbackUriHost), relativeUri: "/api/callbacks"); - CreateCallResult createCallResult = await callAutomationClient.CreateCallAsync( - options: new CreateCallOptions( - callInvite: new CallInvite(targetIdentity: new CommunicationUserIdentifier(id: targetUserId)), - callbackUri: callbackUri) - { - CallIntelligenceOptions = new CallIntelligenceOptions - { - CognitiveServicesEndpoint = new Uri(uriString: "") - } - }); - targetCallConnectionId = createCallResult.CallConnectionProperties.CallConnectionId; - logger.LogInformation( - "TargetCall: From: CallAutomation, To: {Tgt}, ConnId: {Conn}, CorrId: {Corr}", - targetUserId, targetCallConnectionId, createCallResult.CallConnectionProperties.CorrelationId); - return Results.Ok(); -}).WithTags("Lobby Call Support APIs"); - // Get Participants app.MapGet("/GetParticipants/{connId}", async (string connId, ILogger logger) => { diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json index d114625f..7e551222 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Properties/launchSettings.json @@ -1,12 +1,12 @@ { "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { + "profiles": { "https": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "swagger", - "applicationUrl": "https://localhost:7006", + "applicationUrl": "https://localhost:7006;http://localhost:5143", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json index 0ecadf66..9e03a0ed 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json +++ b/LobbyCallSupportSample/LobbyCallSupportSample/appsettings.json @@ -10,6 +10,5 @@ "cognitiveServiceEndpoint": "", "callbackUriHost": "", "acsLobbyCallReceiver": "", - "acsTargetCallReceiver": "", - "acsTargetCallSender": "" + "acsTargetCallReceiver": "" } \ No newline at end of file diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index e30312bf..b358fd86 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -129,13 +129,15 @@ Before running the application, configure the following settings in the `appSett --- ## Running the App Locally + 1. **Generate ACS identities** for lobby and target participants in **Azure Portal**. 2. **Setup EventSubscription** for incoming calls: - - Set up a Web hook(`https:///callbacks/incomingcall`) for callback. + - Set up a Web hook(`https:///callbacks/LobbyCallSupportEventHandler`) for callback. - Add Filter: - Key: `data.to.rawid`, operator: `string contains`, value: `acsLobbyCallReceiver, acsTargetCallReceiver` -3. Define a **WebSocket** in `program.cs` for client-server communication. -4. Use the **JS Client App**, Navigate to `LobbyCallSupport-Client` folder in https://github.com/Azure-Samples/communication-services-javascript-quickstarts. +3. Use the **JS Client App**, Navigate to `LobbyCallSupport-Client` folder in https://github.com/Azure-Samples/communication-services-javascript-quickstarts. +4. Use the **WebSocket**, `ws:///ws` in client app for client-server communication. + --- ## Workflow From c933c075ff18593bf67fe2e172d920830b1ff1a6 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Tue, 18 Nov 2025 15:28:07 +0530 Subject: [PATCH 24/27] Lobby Call Support Sample - readme.md updates --- LobbyCallSupportSample/LobbyCallSupportSample/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index b358fd86..7b7332ac 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -132,11 +132,11 @@ Before running the application, configure the following settings in the `appSett 1. **Generate ACS identities** for lobby and target participants in **Azure Portal**. 2. **Setup EventSubscription** for incoming calls: - - Set up a Web hook(`https:///callbacks/LobbyCallSupportEventHandler`) for callback. + - Set up a Web hook(`https:///api/LobbyCallSupportEventHandler`) for callback. - Add Filter: - Key: `data.to.rawid`, operator: `string contains`, value: `acsLobbyCallReceiver, acsTargetCallReceiver` 3. Use the **JS Client App**, Navigate to `LobbyCallSupport-Client` folder in https://github.com/Azure-Samples/communication-services-javascript-quickstarts. -4. Use the **WebSocket**, `ws:///ws` in client app for client-server communication. +4. Use the **WebSocket**, `wss:///ws` in client app for client-server communication. --- From 6a7b48ee59e941f314b31595d846d9d0016cf069 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Tue, 18 Nov 2025 16:29:37 +0530 Subject: [PATCH 25/27] Lobby Call Support Sample - logged event in /callbacks --- LobbyCallSupportSample/LobbyCallSupportSample/Program.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 09a5b5b9..7b5d39e1 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -110,10 +110,11 @@ { var callEvent = CallAutomationEventParser.Parse(cloudEvent); var callConnection = callAutomationClient.GetCallConnection(callConnectionId: callEvent.CallConnectionId); + logger.LogInformation("~~~ /api/callbacks ~~~\n Event: {callEvent}", callEvent); switch (callEvent) { case CallConnected callConnected when (callConnected.OperationContext ?? "") == "LobbyCall": - logger.LogInformation("~~~ /api/callbacks ~~~\nCallConnected: {ConnId}", callConnected.CallConnectionId); + logger.LogInformation("\nCallConnected: {ConnId}", callConnected.CallConnectionId); CallConnectionProperties callProperties = callConnection.GetCallConnectionProperties(); lobbyUserId = callProperties.Source.RawId; lobbyCallConnectionId = callProperties.CallConnectionId; From 25cfaa88e9f4086d609d02e73e9a273783a35749 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Thu, 20 Nov 2025 19:12:30 +0530 Subject: [PATCH 26/27] Lobby Call Support Sample - readme.md updates --- .../LobbyCallSupportSample/Program.cs | 2 +- .../LobbyCallSupportSample/readme.md | 21 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index 7b5d39e1..76a8ccbd 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -230,7 +230,7 @@ await webSocket.CloseAsync( fromCall: lobbyCallConnectionId)); var rawResponse = moveResult.GetRawResponse(); if (rawResponse.Status is >= 200 and <= 299) - logger.LogInformation("Move successful"); + logger.LogInformation("Move Participant operation is initiated."); else throw new Exception(message: $"Move failed: {rawResponse.Status}"); } diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 7b7332ac..8fb1d3d3 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -78,9 +78,10 @@ dotnet tool install -g Microsoft.DevTunnels.Client devtunnel login # Create and start a tunnel -devtunnel port create -p 7006 -devtunnel host start +devtunnel host -p 7006 ``` + +--- ## Configuration Before running the application, configure the following settings in the `appSettings.json` file: @@ -147,11 +148,23 @@ Before running the application, configure the following settings in the `appSett - Add user ID for `acsTargetCallReceiver`. - Click **Start Call**. - Incoming call from target sender → server answers → expect `Call Connected` event. -- Lobby user calls `acsLobbyCallReceiver` → automated voice plays: `You are currently in a lobby call, we will notify the admin that you are waiting.` +- **Lobby user** calls `acsLobbyCallReceiver` → automated voice plays: `You are currently in a lobby call, we will notify the admin that you are waiting.` - Target call receives notification (a confirm dialog): `A user is waiting in lobby, do you want to add them to your call?` -- If confirmed → expect **MoveParticipantSucceeded** event → lobby user joins target call. +- If confirmed, **Lobby user must accept the call when prompted to move in call test app** → expect **MoveParticipantSucceeded** event → lobby user joins target call. +- **If user does not accept the move call prompt → lobby user remains in lobby call.** - If Target user declined → lobby user will not be moved to target call. +--- + +## API Testing with Swagger + +You can explore and test the available API endpoints using the built-in Swagger UI: + +- **Swagger URL:** + [https://localhost:7006/swagger/index.html](https://localhost:7006/swagger/index.html) + +> If running in a dev tunnel or cloud environment, replace `localhost:7006` with your tunnel's public URL (e.g., `https://.devtunnels.ms/swagger/index.html`). + --- ## Troubleshooting From edaad2fc1d3c52ad9e19eec36e7d6c89853ad688 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Thu, 20 Nov 2025 19:38:00 +0530 Subject: [PATCH 27/27] Lobby Call Support Sample - readme.md updates --- .../Resources/Lobby_Call_Support_Scenario.jpg | Bin 128065 -> 149431 bytes .../LobbyCallSupportSample/readme.md | 14 ++++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Resources/Lobby_Call_Support_Scenario.jpg b/LobbyCallSupportSample/LobbyCallSupportSample/Resources/Lobby_Call_Support_Scenario.jpg index 92225d4e602310278e4a69aed681d388a4290064..0bfb895eeed3de8022a7b614bfbd5d0a060ddfad 100644 GIT binary patch literal 149431 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 literal 128065 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

AUR$p1PMe$*`cVx3$&410_zLaO77Iz7D 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 z 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 diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 8fb1d3d3..8d1f5b45 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -123,15 +123,17 @@ Before running the application, configure the following settings in the `appSett "cognitiveServiceEndpoint": "https://", "callbackUriHost": "https://.devtunnels.ms", "acsLobbyCallReceiver": "8:acs:", - "acsTargetCallReceiver": "8:acs:", - "acsTargetCallSender": "8:acs:" + "acsTargetCallReceiver": "8:acs:" } ``` --- ## Running the App Locally -1. **Generate ACS identities** for lobby and target participants in **Azure Portal**. +1. **Generate ACS identities** for lobby and target participants in **Azure Portal**. 3 users are needed: + - `acsLobbyCallReceiver` – Lobby call receiver. + - `acsTargetCallReceiver` – Target call receiver. + - `Sender` – Target call sender. 2. **Setup EventSubscription** for incoming calls: - Set up a Web hook(`https:///api/LobbyCallSupportEventHandler`) for callback. - Add Filter: @@ -144,11 +146,11 @@ Before running the application, configure the following settings in the `appSett ## Workflow - Start target call in client app `LobbyCallSupport-Client`: - - Add token for `acsTargetCallSender`. - - Add user ID for `acsTargetCallReceiver`. + - Input token for `Sender` behalf of Target call sender. + - Input user ID for `acsTargetCallReceiver` for Target call receiver. - Click **Start Call**. - Incoming call from target sender → server answers → expect `Call Connected` event. -- **Lobby user** calls `acsLobbyCallReceiver` → automated voice plays: `You are currently in a lobby call, we will notify the admin that you are waiting.` +- From a test app or ACS client, **Lobby user** calls `acsLobbyCallReceiver` → CA answers call and automated voice plays: `You are currently in a lobby call, we will notify the admin that you are waiting.` - Target call receives notification (a confirm dialog): `A user is waiting in lobby, do you want to add them to your call?` - If confirmed, **Lobby user must accept the call when prompted to move in call test app** → expect **MoveParticipantSucceeded** event → lobby user joins target call. - **If user does not accept the move call prompt → lobby user remains in lobby call.**

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", - "cognitiveServiceEndpoint": "", - "callbackUriHost": "", - "textToPlayToLobbyUser": "You are currently in a lobby call, we will notify the admin that you are waiting.", - "confirmMessageToTargetCall": "A user is waiting in lobby, do you want to add the lobby user to your call?", - "acsGeneratedIdForLobbyCallReceiver": "", - "acsGeneratedIdForTargetCallReceiver": "", - "acsGeneratedIdForTargetCallSender": "", - "socketToken": "" + "acsConnectionString": "", + "cognitiveServiceEndpoint": "", + "callbackUriHost": "", + "textToPlayToLobbyUser": "", + "confirmMessageToTargetCall": "", + "acsGeneratedIdForLobbyCallReceiver": "", + "acsGeneratedIdForTargetCallReceiver": "", + "acsGeneratedIdForTargetCallSender": "" } \ No newline at end of file diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 3d304617..812efac0 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -4,7 +4,7 @@ # Call Automation - Lobby Call Support Sample -In this sample, we cover how you can use Call Automation SDK to support Lobby Call where we join Lobby call users to a target call upon confirmation of admin in the target call. +This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Call scenario. In this setup, users initially join a lobby call and remain on hold until an user in the target call confirms their participation. Once approved, the bot automatically moves the lobby user to the designated target call. # Design @@ -12,9 +12,6 @@ In this sample, we cover how you can use Call Automation SDK to support Lobby Ca ![Lobby Call Support](./Resources/Lobby_Call_Support_Scenario.jpg) ## Prerequisites - -- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F). -- A deployed Communication Services resource. [Create a Communication Services resource](https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource). - A [phone number](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number) in your Azure Communication Services resource that can make outbound calls. NB: phone numbers are not available in free subscriptions. - Create Azure AI Multi Service resource. For details, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). - Create and host a Azure Dev Tunnel. Instructions [here](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started) @@ -29,7 +26,11 @@ In this sample, we cover how you can use Call Automation SDK to support Lobby Ca ``` npx webpack serve --config webpack.config.js ``` +4. UI of client application will be available at `http://localhost:/` and will look like below. + +![Lobby Call Support](./Resources/client-app-ui.jpg) +5. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the Azure Portal(ACS Resource -> Identities & User Access Tokens -> Generate Identity and USER ACCESS TOKEN). ### Setup and host your Azure DevTunnel [Azure DevTunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview) is an Azure service that enables you to share local web services hosted on the internet. Use the commands below to connect your local development environment to the public internet. This creates a tunnel with a persistent endpoint URL and which allows anonymous access. We will then use this endpoint to notify your application of calling events from the ACS Call Automation service. @@ -43,39 +44,28 @@ Open `appSettings.json` file to configure the following settings - This is used to play media to the participants in the call. - For more information, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). 3. `callbackUriHost`: Base url of the app. (For local development use dev tunnel url) -4. `confirmMessageToTargetCall`: Notification message to be played to the target call participants when they are moved from lobby call to target call. - - This is used to notify the target call participants that they are being moved from lobby call to target call. - - For more information, see [Play media in a call](https://learn.microsoft.com/en-us/azure/communication-services/concepts/calls/play-media). -5. `textToPlayToLobbyUser`: Text to be played to the lobby call user when they are waiting in the lobby. - - This is used to notify the lobby call user that they are waiting in the lobby. - - For more information, see [Play media in a call](https://learn.microsoft.com/en-us/azure/communication-services/concepts/calls/play-media). -6. `acsGeneratedIdForLobbyCallReceiver`: ACS Inbound Phone Number -7. `acsGeneratedIdForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time -8. `acsGeneratedIdForTargetCallSender`: ACS identity generated using web client -9. `socketToken`: ACS identity generated using web client +4. `acsGeneratedIdForLobbyCallReceiver`: ACS Inbound Phone Number +5. `acsGeneratedIdForTargetCallReceiver`: ACS Phone Number to make the first call, external user number in real time +6. `acsGeneratedIdForTargetCallSender`: ACS identity generated using web client ## Run app locally 1. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = , `. 2. Setup the following keys in the config/constants - ```"acsConnectionString": "", + ``` + "acsConnectionString": "", "cognitiveServiceEndpoint": "", "callbackUriHost": "", - "textToPlayToLobbyUser": "You are currently in a lobby call, we will notify the admin that you are waiting.", - "confirmMessageToTargetCall": "A user is waiting in lobby, do you want to add the lobby user to your call?", "acsGeneratedIdForLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) "acsGeneratedIdForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) - "acsGeneratedIdForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal) - "socketToken": ""(Token associated with in Azure Portal)``` -3. Define a websocket in your application(program.cs) to send and receive messages from and to client application(JS Hero App in this case). -4. Define a Client application that receives and responds to server notifications. Client application is available at . -5. Enter and validate user token in client app to send calls. -6. Start call to ``. -7. Expect Call Connected evennt in /callbacks -8. Start a call from ACS Test app(angular) to acsGeneratedIdForLobbyCallReceiver -9. Call will be answered and automated voice will be played to lobby user with the text ``. -10. Once the play completed, Target call will be notified with ``. -11. Once the Target call confirms from client application, Move `` in the backend sample. -12. If Target user says no, then no MOVE will be performed. -13. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. -14. Check `/Getparticipants` endpoint be called with Target call id, Target call must have the recent lobby user in the call. \ No newline at end of file + "acsGeneratedIdForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` +3. Define a websocket with url as "/ws" in your application(program.cs) to send and receive messages from and to the client application. +4. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at . +5. Start call to `` (use the web client to initiate the call). +6. Expect Call Connected event in /callbacks. +8. Call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` +9. Once the play completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. +10. Once the Target call confirms from client application, Move `ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER` in the backend sample. +11. If Target user says no, then no MOVE will be performed. +12. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. +13. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobbyy user(as lobby user is already moved into the target call). \ No newline at end of file From 4f45054797fea77d2b9120458414ba78a1b1244f Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Fri, 17 Oct 2025 14:51:39 +0530 Subject: [PATCH 09/27] Lobby Call Support - updates to readme.md file --- .../LobbyCallSupportSample/readme.md | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 812efac0..aa41d71f 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -1,10 +1,10 @@ | page_type | languages | products | | --------- | --------------------------------------- | --------------------------------------------------------------------------- | -| sample |
DotNet
|
azureazure-communication-services
| +| sample |
DotNetJava Script
|
azureazure-communication-services
| # Call Automation - Lobby Call Support Sample -This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Call scenario. In this setup, users initially join a lobby call and remain on hold until an user in the target call confirms their participation. Once approved, the bot automatically moves the lobby user to the designated target call. +This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Callscenario. In this setup, users initially join a lobby call (Call - I) and remain on hold until an user in the target call (Call - II) confirms their participation. Once approved, the bot automatically moves the lobby user to the target call. # Design @@ -50,8 +50,10 @@ Open `appSettings.json` file to configure the following settings ## Run app locally -1. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = , `. -2. Setup the following keys in the config/constants +1. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the Azure Portal(ACS Resource ? Identities & User Access Tokens ? Generate Identity and USER ACCESS TOKEN). +2. Setup EventSubscription(Incoming) with filter for `TO.DATA.RAWID = , `. +3. Setup webhook for Incoming calls to point to `https:///callbacks/incomingcall` in EventSubscription(Incoming). +4. Setup the following keys in the config/constants ``` "acsConnectionString": "", "cognitiveServiceEndpoint": "", @@ -59,13 +61,16 @@ Open `appSettings.json` file to configure the following settings "acsGeneratedIdForLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) "acsGeneratedIdForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) "acsGeneratedIdForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` -3. Define a websocket with url as "/ws" in your application(program.cs) to send and receive messages from and to the client application. -4. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at . -5. Start call to `` (use the web client to initiate the call). +4. Define a websocket with url as "/ws" in your application(program.cs) to send and receive messages from and to the client application. +5. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at . + Start the target call in Client application, + - Add token of target call sender(token would be generated in Azure user & tokens section). + - Add user id of the target call receiver ``. + - Click on `Start Call` button to initiate the call. 6. Expect Call Connected event in /callbacks. -8. Call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` -9. Once the play completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. -10. Once the Target call confirms from client application, Move `ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER` in the backend sample. -11. If Target user says no, then no MOVE will be performed. -12. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. -13. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobbyy user(as lobby user is already moved into the target call). \ No newline at end of file +7. Call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` +8. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. +9. Once the Target call confirms from client application, Move `ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER` in the backend sample. +10. If Target user says no, then no MOVE will be performed. +11. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. +12. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobbyy user(as lobby user is already moved into the target call). \ No newline at end of file From 5571a6e40429e0b78a4737244948b0b8fd4720d6 Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Fri, 17 Oct 2025 15:34:43 +0530 Subject: [PATCH 10/27] Readme.md tweaks --- LobbyCallSupportSample/LobbyCallSupportSample/readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index aa41d71f..7e51b70c 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -12,6 +12,8 @@ This sample demonstrates how to utilize the Call Automation SDK to implement a L ![Lobby Call Support](./Resources/Lobby_Call_Support_Scenario.jpg) ## Prerequisites +- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F). +- A deployed Communication Services resource. [Create a Communication Services resource](https://docs.microsoft.com/azure/communication-services/quickstarts/create-communication-resource). - A [phone number](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/telephony/get-phone-number) in your Azure Communication Services resource that can make outbound calls. NB: phone numbers are not available in free subscriptions. - Create Azure AI Multi Service resource. For details, see [Create an Azure AI Multi service](https://learn.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account). - Create and host a Azure Dev Tunnel. Instructions [here](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started) From ce297b6ecb2e30e54d99018ec56b4db4c9a807fe Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Fri, 17 Oct 2025 17:12:41 +0530 Subject: [PATCH 11/27] Readme.md tweaks --- .../LobbyCallSupportSample/readme.md | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md index 7e51b70c..5be8db80 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/readme.md +++ b/LobbyCallSupportSample/LobbyCallSupportSample/readme.md @@ -4,7 +4,7 @@ # Call Automation - Lobby Call Support Sample -This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Callscenario. In this setup, users initially join a lobby call (Call - I) and remain on hold until an user in the target call (Call - II) confirms their participation. Once approved, the bot automatically moves the lobby user to the target call. +This sample demonstrates how to utilize the Call Automation SDK to implement a Lobby Callscenario. Users initially join a lobby call (Call - I) and remain on hold until an user in the target call (Call - II) confirms their participation. Once approved, the bot automatically moves the lobby user to the target call. # Design @@ -30,9 +30,9 @@ This sample demonstrates how to utilize the Call Automation SDK to implement a L ``` 4. UI of client application will be available at `http://localhost:/` and will look like below. -![Lobby Call Support](./Resources/client-app-ui.jpg) + ![Lobby Call Support](./Resources/client-app-ui.jpg) + -5. Generate an Azure Communication Services identity for the lobby call receiver and target call receiver. You can do this from the Azure Portal(ACS Resource -> Identities & User Access Tokens -> Generate Identity and USER ACCESS TOKEN). ### Setup and host your Azure DevTunnel [Azure DevTunnels](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview) is an Azure service that enables you to share local web services hosted on the internet. Use the commands below to connect your local development environment to the public internet. This creates a tunnel with a persistent endpoint URL and which allows anonymous access. We will then use this endpoint to notify your application of calling events from the ACS Call Automation service. @@ -63,16 +63,17 @@ Open `appSettings.json` file to configure the following settings "acsGeneratedIdForLobbyCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) "acsGeneratedIdForTargetCallReceiver": "",(Generate Voice Calling Identity in Azure Portal) "acsGeneratedIdForTargetCallSender": "",(Generate Voice Calling Identity in Azure Portal)``` -4. Define a websocket with url as "/ws" in your application(program.cs) to send and receive messages from and to the client application. -5. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at . - Start the target call in Client application, +5. Define a websocket with url as `ws://your-websocket-server-url:port/ws` in your application(program.cs) to send and receive messages from and to the client application. +6. Define a Client application(JS Hero App in this case) that receives and responds to server notifications. Client application is available at `http://localhost:/`. + +7. Start the target call in Client application, - Add token of target call sender(token would be generated in Azure user & tokens section). - Add user id of the target call receiver ``. - Click on `Start Call` button to initiate the call. -6. Expect Call Connected event in /callbacks. -7. Call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` -8. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. -9. Once the Target call confirms from client application, Move `ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER` in the backend sample. -10. If Target user says no, then no MOVE will be performed. -11. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. -12. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobbyy user(as lobby user is already moved into the target call). \ No newline at end of file +8. Expect Call Connected event in /callbacks as the server app answers incoming call from target call sender to target call receiver. +9. Start a call from ACS Test app(angular) to `acsGeneratedIdForLobbyCallReceiver`, call will be answered by the server app and automated voice will be played to lobby user with the text `You are currently in a lobby call, we will notify the admin that you are waiting.` +10. Once the play is completed, Target call will be notified with `A user is waiting in lobby, do you want to add the lobby user to your call?`. +11. Once the Target call confirms from client application, Move `ACS_GENERATED_ID_FOR_LOBBY_CALL_RECEIVER` in the backend sample. +12. If Target user says no, then no MOVE will be performed. +13. Ensure MoveParticipantSucceeded event is received in `/callbacks` endpoint. +14. Ensure the output in the logs shows the the additional lobby user in the target call. The number of participants in the target call are increased by adding the lobby user, then lobby call gets disconnected after the moving the lobbyy user(as lobby user is already moved into the target call). \ No newline at end of file From e18623e21ce9e29048a919d379f36f027ae6f3de Mon Sep 17 00:00:00 2001 From: "Kishore Uppu (Centific Technologies Inc)" Date: Thu, 23 Oct 2025 19:55:06 +0530 Subject: [PATCH 12/27] Lobby Support Sample - addressed comments in PR#228 --- .../InstructionToDeploy.txt | 16 ------ .../LobbyCallSupportSample/Program.cs | 47 ++++++++++++++++++ .../Resources/client-app-ui.jpg | Bin 18762 -> 0 bytes .../LobbyCallSupportSample/appsettings.json | 14 +++--- .../LobbyCallSupportSample/readme.md | 38 +++++++------- 5 files changed, 74 insertions(+), 41 deletions(-) delete mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt delete mode 100644 LobbyCallSupportSample/LobbyCallSupportSample/Resources/client-app-ui.jpg diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt b/LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt deleted file mode 100644 index 83a9af5c..00000000 --- a/LobbyCallSupportSample/LobbyCallSupportSample/InstructionToDeploy.txt +++ /dev/null @@ -1,16 +0,0 @@ -Install Git Bash - -Open Git Bash - -Navigate to deployment file location - -#://GA5ContosoApp/GA5ContosoApp - -Execute following command to create executable. -chmod +x azure-deploy.sh - -Execute following command to deploy -./azure-deploy.sh - -https://.scm.azurewebsites.net/swagger/index.html - diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs index b9c9e55a..8e13dad0 100644 --- a/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs +++ b/LobbyCallSupportSample/LobbyCallSupportSample/Program.cs @@ -254,6 +254,53 @@ Playing Media to Lobby Call.. Call Connection Id: {moveParticipantSucceeded.CallConnectionId} Correlation Id: {moveParticipantSucceeded.CorrelationId} """); + // move + // Get the updated participants list + msgLog.AppendLine($""" + + ~~~~~~~~~~~~ Participants in Target Connection({targetCallConnectionId}) ~~~~~~~~~~~~ + """); + try + { + CallConnection targetConnection = client.GetCallConnection(moveParticipantSucceeded.CallConnectionId); + var participants = await targetConnection.GetParticipantsAsync(); + + var participantinfo = participants.Value.Select(p => new + { + p.Identifier.RawId, + Type = p.Identifier.GetType().Name, + PhoneNumber = p.Identifier is PhoneNumberIdentifier phone ? phone.PhoneNumber : null, + AcsUserId = p.Identifier is CommunicationUserIdentifier user ? user.Id : null, + }).OrderBy(p => p.AcsUserId) // to display phone numbers first + .Select(p => new + { + Info = string.IsNullOrWhiteSpace(p.AcsUserId) + ? $"{p.Type} - RawId: {p.RawId}, Phone: {p.PhoneNumber}" // extra space for alignment + : $"{p.Type} - RawId: {p.AcsUserId}" + }); + + if (!participantinfo.Any()) + { + Console.WriteLine("No participants found for the specified call connection."); + } + else + { + msgLog.AppendLine($""" + No of Participants: {participantinfo.Count()} + Participants: + ------------- + {string.Join("\n", participantinfo.Select((p, index) => $"{index + 1}. {p.Info}"))} + """); + Console.WriteLine(msgLog.ToString()); + } + } + catch (Exception ex) + { + Console.WriteLine("Error getting participants for call {targetCallConnectionId}: {ex.Message}"); + + } + // end: Get the updated participants list + // end: move } else if (parsedEvent is CallDisconnected callDisconnected) { diff --git a/LobbyCallSupportSample/LobbyCallSupportSample/Resources/client-app-ui.jpg b/LobbyCallSupportSample/LobbyCallSupportSample/Resources/client-app-ui.jpg deleted file mode 100644 index 3b461a337a1d0fb6fcaf65500e47baf38e0d68d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18762 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