diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs index e82908a0a..095f3d256 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioInboundController.cs @@ -107,6 +107,12 @@ await HookEmitter.Emit(_services, response.Redirect(new Uri($"{_settings.CallbackHost}/twilio/voice/reply/{seqNum}?agent-id={request.AgentId}&conversation-id={request.ConversationId}&{twilio.GenerateStatesParameter(request.States)}"), HttpMethod.Post); } } + + _ = Task.Run(async () => + { + await Task.Delay(1500); + await twilio.StartRecording(request.CallSid, request.AgentId, request.ConversationId); + }); } await HookEmitter.Emit(_services, async hook => diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs index 65b2a5adf..4e4b1c751 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioRecordController.cs @@ -38,6 +38,10 @@ public async Task PhoneRecordingStatus(ConversationalVoiceRequest // recording completed await HookEmitter.Emit(_services, x => x.OnRecordingCompleted(request)); } + else + { + _logger.LogError($"Unknown record status: {request.CallStatus}, {request.CallSid}"); + } return Ok(); } diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs index b5bbb6bca..42582f707 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioVoiceController.cs @@ -214,7 +214,7 @@ public async Task ReplyCallerMessage(ConversationalVoiceRequest req var reply = await sessionManager.GetAssistantReplyAsync(request.ConversationId, request.SeqNum); VoiceResponse response; - + if (request.AIResponseWaitTime > 10) { // Wait AI Response Timeout @@ -381,19 +381,23 @@ await HookEmitter.Emit(_services, else if (request.CallStatus == "canceled") { await HookEmitter.Emit(_services, - async hook => - { - if (hook.IsMatch(request)) await hook.OnCallCanceledStatus(request); + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallCanceledStatus(request); }); } else if (request.CallStatus == "failed") { await HookEmitter.Emit(_services, - async hook => - { - if (hook.IsMatch(request)) await hook.OnCallFailedStatus(request); + async hook => + { + if (hook.IsMatch(request)) await hook.OnCallFailedStatus(request); }); } + else + { + _logger.LogError($"Unknown call status: {request.CallStatus}, {request.CallSid}"); + } return Ok(); } diff --git a/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs b/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs index c0254c1ea..7bc95382b 100644 --- a/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs +++ b/src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs @@ -6,6 +6,8 @@ using BotSharp.Plugin.Twilio.Interfaces; using BotSharp.Plugin.Twilio.Models; using Twilio.Jwt.AccessToken; +using Twilio.Rest.Api.V2010.Account.Call; +using Task = System.Threading.Tasks.Task; using Token = Twilio.Jwt.AccessToken.Token; namespace BotSharp.Plugin.Twilio.Services; @@ -122,6 +124,22 @@ public VoiceResponse ReturnNoninterruptedInstructions(ConversationalVoiceRespons return response; } + public async Task StartRecording(string callSid, string agentId, string conversationId) + { + if (_settings.RecordingEnabled) + { + // https://help.twilio.com/articles/360010317333-Recording-Incoming-Twilio-Voice-Calls + var recordStatusUrl = $"{_settings.CallbackHost}/twilio/record/status?agent-id={agentId}&conversation-id={conversationId}"; + var recording = await RecordingResource.CreateAsync(pathCallSid: callSid, + recordingStatusCallback: new Uri(recordStatusUrl), + trim: "trim-silence", + recordingChannels: "dual", + recordingTrack: "both"); + + _logger.LogInformation($"Recording started: {recording.CallSid} {recording.Sid}"); + } + } + public VoiceResponse HangUp(string speechPath) { var response = new VoiceResponse();