BotSharp/src/Plugins/BotSharp.Plugin.Twilio/Controllers/TwilioStreamController.cs

119 lines
3.9 KiB
C#
Raw Normal View History

2025-02-07 17:18:47 +00:00
using BotSharp.Abstraction.Infrastructures;
2025-02-27 04:40:50 +00:00
using BotSharp.Abstraction.Infrastructures.Enums;
2025-02-07 17:18:47 +00:00
using BotSharp.Core.Infrastructures;
using BotSharp.Plugin.Twilio.Interfaces;
using BotSharp.Plugin.Twilio.Models;
using BotSharp.Plugin.Twilio.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
2025-02-07 19:41:20 +00:00
using Conversation = BotSharp.Abstraction.Conversations.Models.Conversation;
2025-02-07 17:18:47 +00:00
namespace BotSharp.Plugin.Twilio.Controllers;
public class TwilioStreamController : TwilioController
{
private readonly TwilioSetting _settings;
private readonly IServiceProvider _services;
private readonly IHttpContextAccessor _context;
private readonly ILogger _logger;
public TwilioStreamController(TwilioSetting settings, IServiceProvider services, IHttpContextAccessor context, ILogger<TwilioStreamController> logger)
{
_settings = settings;
_services = services;
_context = context;
_logger = logger;
}
[ValidateRequest]
[HttpPost("twilio/stream")]
public async Task<TwiMLResult> InitiateStreamConversation(ConversationalVoiceRequest request)
{
var text = JsonSerializer.Serialize(request);
if (request?.CallSid == null)
{
throw new ArgumentNullException(nameof(VoiceRequest.CallSid));
}
VoiceResponse response = null;
var instruction = new ConversationalVoiceResponse
{
2025-02-11 23:27:07 +00:00
SpeechPaths = [],
2025-02-07 17:18:47 +00:00
ActionOnEmptyResult = true
};
2025-02-10 23:28:03 +00:00
2025-02-11 23:27:07 +00:00
if (_context.HttpContext.Request.Query.ContainsKey("init_audio_file"))
{
request.InitAudioFile = _context.HttpContext.Request.Query["init_audio_file"];
instruction.SpeechPaths.Add(request.InitAudioFile);
2025-02-11 23:27:07 +00:00
}
2025-02-10 23:28:03 +00:00
if (_context.HttpContext.Request.Query.ContainsKey("conversation_id"))
{
request.ConversationId = _context.HttpContext.Request.Query["conversation_id"];
}
2025-02-07 17:18:47 +00:00
await HookEmitter.Emit<ITwilioSessionHook>(_services, async hook =>
{
await hook.OnSessionCreating(request, instruction);
}, new HookEmitOption
{
OnlyOnce = true
});
2025-02-27 04:40:50 +00:00
request.ConversationId = await InitConversation(request);
2025-02-07 17:18:47 +00:00
var twilio = _services.GetRequiredService<TwilioService>();
2025-02-10 23:28:03 +00:00
response = twilio.ReturnBidirectionalMediaStreamsInstructions(request.ConversationId, instruction);
2025-02-07 17:18:47 +00:00
2025-02-07 19:41:20 +00:00
await HookEmitter.Emit<ITwilioSessionHook>(_services, async hook =>
2025-02-07 17:18:47 +00:00
{
await hook.OnSessionCreated(request);
}, new HookEmitOption
{
OnlyOnce = true
2025-02-07 19:41:20 +00:00
});
2025-02-07 17:18:47 +00:00
return TwiML(response);
}
2025-02-07 19:41:20 +00:00
2025-02-27 04:40:50 +00:00
private async Task<string> InitConversation(ConversationalVoiceRequest request)
2025-02-07 19:41:20 +00:00
{
var convService = _services.GetRequiredService<IConversationService>();
2025-02-10 23:28:03 +00:00
var conversation = await convService.GetConversation(request.ConversationId);
2025-02-11 23:27:07 +00:00
if (conversation == null)
2025-02-10 23:28:03 +00:00
{
2025-02-11 23:27:07 +00:00
var conv = new Conversation
{
2025-02-27 04:52:14 +00:00
AgentId = request.AgentId ?? _settings.AgentId,
2025-02-11 23:27:07 +00:00
Channel = ConversationChannel.Phone,
ChannelId = request.CallSid,
2025-02-27 04:40:50 +00:00
Title = $"Incoming phone call from {request.From}",
2025-02-11 23:27:07 +00:00
Tags = [],
};
conversation = await convService.NewConversation(conv);
2025-02-10 23:28:03 +00:00
}
2025-02-07 19:41:20 +00:00
var states = new List<MessageState>
{
new("channel", ConversationChannel.Phone),
new("calling_phone", request.From),
new("twilio_call_sid", request.CallSid),
2025-02-27 04:40:50 +00:00
// Enable lazy routing mode to optimize realtime experience
new(StateConst.ROUTING_MODE, "lazy"),
2025-02-07 19:41:20 +00:00
};
if (request.InitAudioFile != null)
{
states.Add(new("init_audio_file", request.InitAudioFile));
}
2025-02-11 23:27:07 +00:00
convService.SetConversationId(conversation.Id, states);
2025-02-07 19:41:20 +00:00
convService.SaveStates();
2025-02-27 04:40:50 +00:00
return conversation.Id;
2025-02-07 19:41:20 +00:00
}
2025-02-07 17:18:47 +00:00
}