Skip to content

fix bug of twilio #610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using BotSharp.Abstraction.Agents.Enums;
using BotSharp.Abstraction.Conversations.Enums;
using BotSharp.Abstraction.Repositories.Filters;
using BotSharp.Abstraction.Users;

Expand Down Expand Up @@ -47,20 +48,26 @@ public override async Task OnMessageReceived(RoleDialogModel message)
}
}

var states = _services.GetRequiredService<IConversationStateService>();
var channel = states.GetState("channel");

// Check the number of conversations
var user = _services.GetRequiredService<IUserIdentity>();
var convService = _services.GetRequiredService<IConversationService>();
var results = await convService.GetConversations(new ConversationFilter
if (channel != ConversationChannel.Phone && channel != ConversationChannel.Email)
{
UserId = user.Id,
StartTime = DateTime.UtcNow.AddHours(-24),
});
var user = _services.GetRequiredService<IUserIdentity>();
var convService = _services.GetRequiredService<IConversationService>();
var results = await convService.GetConversations(new ConversationFilter
{
UserId = user.Id,
StartTime = DateTime.UtcNow.AddHours(-24),
});

if (results.Count > rateLimit.MaxConversationPerDay)
{
message.Content = $"The number of conversations you have exceeds the system maximum of {rateLimit.MaxConversationPerDay}";
message.StopCompletion = true;
return;
if (results.Count > rateLimit.MaxConversationPerDay)
{
message.Content = $"The number of conversations you have exceeds the system maximum of {rateLimit.MaxConversationPerDay}";
message.StopCompletion = true;
return;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using BotSharp.Plugin.Twilio.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Twilio.Http;

namespace BotSharp.Plugin.Twilio.Controllers;

Expand Down Expand Up @@ -35,7 +36,7 @@ public TwiMLResult InitiateConversation(VoiceRequest request, [FromQuery] string
string conversationId = $"TwilioVoice_{request.CallSid}";
var twilio = _services.GetRequiredService<TwilioService>();
var url = $"twilio/voice/{conversationId}/receive/0?states={states}";
var response = twilio.ReturnInstructions("twilio/welcome.mp3", url, true);
var response = twilio.ReturnInstructions(new List<string> { "twilio/welcome.mp3" }, url, true);
return TwiML(response);
}

Expand All @@ -53,17 +54,10 @@ public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversat
messages.Add(text);
await sessionManager.StageCallerMessageAsync(conversationId, seqNum, text);
}

VoiceResponse response;
if (messages.Count == 0 && seqNum == 0)
{
response = twilio.ReturnInstructions("twilio/welcome.mp3", $"twilio/voice/{conversationId}/receive/{seqNum}?states={states}", true, timeout: 2);
}
else
if (messages.Any())
{
if (messages.Count == 0)
{
messages = await sessionManager.RetrieveStagedCallerMessagesAsync(conversationId, seqNum - 1);
}
var messageContent = string.Join("\r\n", messages);
var callerMessage = new CallerMessage()
{
Expand All @@ -82,15 +76,21 @@ public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversat
}
await messageQueue.EnqueueAsync(callerMessage);

int audioIndex = Random.Shared.Next(1, 5);
response = twilio.ReturnInstructions($"twilio/hold-on-{audioIndex}.mp3", $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true, 1);
response = new VoiceResponse()
.Redirect(new Uri($"{_settings.CallbackHost}/twilio/voice/{conversationId}/reply/{seqNum}?states={states}"), HttpMethod.Post);
}
else
{
response = twilio.ReturnInstructions(null, $"twilio/voice/{conversationId}/receive/{seqNum}?states={states}", true);
}

return TwiML(response);
}

[ValidateRequest]
[HttpPost("twilio/voice/{conversationId}/reply/{seqNum}")]
public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversationId, [FromRoute] int seqNum, [FromQuery] string states, VoiceRequest request)
public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversationId, [FromRoute] int seqNum,
[FromQuery] string states, [FromQuery] string play, VoiceRequest request)
{
var nextSeqNum = seqNum + 1;
var sessionManager = _services.GetRequiredService<ITwilioSessionManager>();
Expand All @@ -106,25 +106,33 @@ public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversatio
var indication = await sessionManager.GetReplyIndicationAsync(conversationId, seqNum);
if (indication != null)
{
string speechPath;
if (indication.StartsWith('#'))
var speechPaths = new List<string>();
foreach (var text in indication.Split('|'))
{
speechPath = $"twilio/{indication.Substring(1)}";
var seg = text.Trim();
if (seg.StartsWith('#'))
{
speechPaths.Add($"twilio/{seg.Substring(1)}.mp3");
}
else
{
var textToSpeechService = CompletionProvider.GetTextToSpeech(_services, "openai", "tts-1");
var fileService = _services.GetRequiredService<IFileStorageService>();
var data = await textToSpeechService.GenerateSpeechFromTextAsync(seg);
var fileName = $"indication_{seqNum}.mp3";
await fileService.SaveSpeechFileAsync(conversationId, fileName, data);
speechPaths.Add($"twilio/voice/speeches/{conversationId}/{fileName}");
}
}
else
{
var textToSpeechService = CompletionProvider.GetTextToSpeech(_services, "openai", "tts-1");
var fileService = _services.GetRequiredService<IFileStorageService>();
var data = await textToSpeechService.GenerateSpeechFromTextAsync(indication);
var fileName = $"indication_{seqNum}.mp3";
await fileService.SaveSpeechFileAsync(conversationId, fileName, data);
speechPath = $"twilio/voice/speeches/{conversationId}/{fileName}";
}
response = twilio.ReturnInstructions(speechPath, $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true, 2);
response = twilio.ReturnInstructions(speechPaths, $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true);
}
else
{
response = twilio.ReturnInstructions(null, $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true, 1);
response = twilio.ReturnInstructions(new List<string>
{
$"twilio/hold-on-{Random.Shared.Next(1, 5)}.mp3",
$"twilio/typing-{Random.Shared.Next(2, 4)}.mp3"
}, $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true);
}
}
else
Expand All @@ -135,7 +143,7 @@ public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversatio
}
else
{
response = twilio.ReturnInstructions($"twilio/voice/speeches/{conversationId}/{reply.SpeechFileName}", $"twilio/voice/{conversationId}/receive/{nextSeqNum}?states={states}", true);
response = twilio.ReturnInstructions(new List<string> { $"twilio/voice/speeches/{conversationId}/{reply.SpeechFileName}" }, $"twilio/voice/{conversationId}/receive/{nextSeqNum}?states={states}", true);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private async Task ProcessUserMessageAsync(CallerMessage message)
{
reply = new AssistantMessage()
{
ConversationEnd = msg.Instruction.ConversationEnd,
ConversationEnd = msg.Instruction?.ConversationEnd ?? false,
Content = msg.Content,
MessageId = msg.MessageId
};
Expand Down
10 changes: 4 additions & 6 deletions src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public VoiceResponse ReturnInstructions(string message)
return response;
}

public VoiceResponse ReturnInstructions(string speechPath, string callbackPath, bool actionOnEmptyResult, int timeout = 3)
public VoiceResponse ReturnInstructions(List<string> speechPaths, string callbackPath, bool actionOnEmptyResult, int timeout = 2)
{
var response = new VoiceResponse();
var gather = new Gather()
Expand All @@ -80,13 +80,11 @@ public VoiceResponse ReturnInstructions(string speechPath, string callbackPath,
Timeout = timeout > 0 ? timeout : 3,
ActionOnEmptyResult = actionOnEmptyResult
};
if (!string.IsNullOrEmpty(speechPath))
if (speechPaths != null && speechPaths.Any())
{
gather.Play(new Uri($"{_settings.CallbackHost}/{speechPath}"));
if (speechPath.Contains("hold-on-"))
foreach (var speechPath in speechPaths)
{
int audioIndex = Random.Shared.Next(1, 4);
gather.Play(new Uri($"{_settings.CallbackHost}/twilio/typing-{audioIndex}.mp3"));
gather.Play(new Uri($"{_settings.CallbackHost}/{speechPath}"));
}
}
response.Append(gather);
Expand Down