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

115 lines
3.7 KiB
C#
Raw Normal View History

2025-02-07 17:18:47 +00:00
using BotSharp.Abstraction.Infrastructures;
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 Twilio.TwiML.Voice;
using Conversation = BotSharp.Abstraction.Conversations.Models.Conversation;
2025-02-07 17:18:47 +00:00
using Task = System.Threading.Tasks.Task;
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"))
{
instruction.SpeechPaths.Add(_context.HttpContext.Request.Query["init_audio_file"]);
}
2025-02-10 23:28:03 +00:00
if (_context.HttpContext.Request.Query.ContainsKey("conversation_id"))
{
request.ConversationId = _context.HttpContext.Request.Query["conversation_id"];
}
else
{
request.ConversationId = request.CallSid;
}
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-07 22:40:57 +00:00
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
private async Task InitConversation(ConversationalVoiceRequest request)
{
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
{
Id = request.CallSid,
AgentId = _settings.AgentId,
Channel = ConversationChannel.Phone,
ChannelId = request.CallSid,
2025-02-11 23:27:07 +00:00
Title = $"Phone call from {request.From}",
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-07 19:41:20 +00:00
};
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-07 17:18:47 +00:00
}