Skip to content

Commit 8a63815

Browse files
authored
Merge pull request #605 from hchen2020/master
AddTwilioRequestValidation
2 parents 4e83813 + 22fa6e4 commit 8a63815

File tree

11 files changed

+84
-44
lines changed

11 files changed

+84
-44
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace BotSharp.Abstraction.Interpreters.Settings;
2+
3+
public class InterpreterSettings
4+
{
5+
public PythonInterpreterSetting Python { get; set; }
6+
}
7+
8+
public class PythonInterpreterSetting
9+
{
10+
public string PythonDLL { get; set; }
11+
}

src/Infrastructure/BotSharp.Abstraction/Routing/Models/RoutingArgs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ namespace BotSharp.Abstraction.Routing.Models;
33
public class RoutingArgs
44
{
55
[JsonPropertyName("function")]
6-
public string Function { get; set; } = string.Empty;
6+
public string Function { get; set; } = "route_to_agent";
77

88
/// <summary>
99
/// The reason why you select this function or agent

src/Infrastructure/BotSharp.Core/BotSharpCoreExtensions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@
66
using BotSharp.Abstraction.Options;
77
using BotSharp.Abstraction.Messaging.JsonConverters;
88
using BotSharp.Abstraction.Users.Settings;
9+
using BotSharp.Abstraction.Interpreters.Settings;
910

1011
namespace BotSharp.Core;
1112

1213
public static class BotSharpCoreExtensions
1314
{
1415
public static IServiceCollection AddBotSharpCore(this IServiceCollection services, IConfiguration config, Action<BotSharpOptions>? configOptions = null)
1516
{
17+
var interpreterSettings = new InterpreterSettings();
18+
config.Bind("Interpreter", interpreterSettings);
19+
services.AddSingleton(x => interpreterSettings);
20+
21+
services.AddSingleton<DistributedLocker>();
22+
1623
services.AddScoped<ISettingService, SettingService>();
1724
services.AddScoped<IUserService, UserService>();
1825
services.AddSingleton<DistributedLocker>();

src/Infrastructure/BotSharp.Core/Routing/Handlers/RouteToAgentRoutingHandler.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@ public class RouteToAgentRoutingHandler : RoutingHandlerBase, IRoutingHandler
1111

1212
public List<ParameterPropertyDef> Parameters => new List<ParameterPropertyDef>
1313
{
14-
new ParameterPropertyDef("next_action_reason",
14+
/*new ParameterPropertyDef("next_action_reason",
1515
"the reason why route to this virtual agent.",
16-
required: true),
16+
required: true),*/
1717
new ParameterPropertyDef("next_action_agent",
1818
"agent for next action based on user latest response, if user is replying last agent's question, you must route to this agent.",
1919
required: true),
2020
new ParameterPropertyDef("args",
2121
"useful parameters of next action agent, format: { }",
2222
type: "object"),
23-
new ParameterPropertyDef("user_goal_description",
23+
/*new ParameterPropertyDef("user_goal_description",
2424
"user goal based on user initial task.",
25-
required: true),
25+
required: true),*/
2626
new ParameterPropertyDef("user_goal_agent",
27-
"agent who can acheive user initial task, must align with user_goal_description.",
27+
"agent who can acheive user initial task.",
2828
required: true),
2929
new ParameterPropertyDef("conversation_end",
3030
"user is ending the conversation.",

src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/instructions/instruction.liquid

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ Follow these steps to handle user request:
1919
# {{ handler.description}}
2020
{% if handler.parameters and handler.parameters != empty -%}
2121
Parameters:
22-
- function: {{ handler.name }}
2322
{% for p in handler.parameters -%}
2423
- {{ p.name }} {% if p.required -%}(required){%- endif %}: {{ p.description }}{{ "\r\n " }}
2524
{%- endfor %}

src/Plugins/BotSharp.Plugin.PythonInterpreter/InterpreterPlugin.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
using BotSharp.Abstraction.Interpreters.Settings;
12
using BotSharp.Plugin.PythonInterpreter.Hooks;
3+
using Microsoft.AspNetCore.Builder;
4+
using Python.Runtime;
5+
using System.IO;
26

37
namespace BotSharp.Plugin.PythonInterpreter;
48

5-
public class InterpreterPlugin : IBotSharpPlugin
9+
public class InterpreterPlugin : IBotSharpAppPlugin
610
{
711
public string Id => "23174e08-e866-4173-824a-cf1d97afa8d0";
812
public string Name => "Python Interpreter";
@@ -14,4 +18,24 @@ public void RegisterDI(IServiceCollection services, IConfiguration config)
1418
services.AddScoped<IAgentHook, InterpreterAgentHook>();
1519
services.AddScoped<IAgentUtilityHook, InterpreterUtilityHook>();
1620
}
21+
22+
public void Configure(IApplicationBuilder app)
23+
{
24+
var settings = app.ApplicationServices.GetRequiredService<InterpreterSettings>();
25+
26+
// For Python interpreter plugin
27+
if (File.Exists(settings.Python.PythonDLL))
28+
{
29+
Runtime.PythonDLL = settings.Python.PythonDLL;
30+
PythonEngine.Initialize();
31+
PythonEngine.BeginAllowThreads();
32+
}
33+
else
34+
{
35+
Serilog.Log.Error("Python DLL found at {PythonDLL}", settings.Python.PythonDLL);
36+
}
37+
38+
// Shut down the Python engine
39+
// PythonEngine.Shutdown();
40+
}
1741
}

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

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,33 @@
22
using BotSharp.Core.Infrastructures;
33
using BotSharp.Plugin.Twilio.Models;
44
using BotSharp.Plugin.Twilio.Services;
5-
using Microsoft.AspNetCore.Authorization;
5+
using Microsoft.AspNetCore.Http;
66
using Microsoft.AspNetCore.Mvc;
7-
using System.IdentityModel.Tokens.Jwt;
87

98
namespace BotSharp.Plugin.Twilio.Controllers;
109

11-
[AllowAnonymous]
12-
[Route("twilio/voice")]
1310
public class TwilioVoiceController : TwilioController
1411
{
1512
private readonly TwilioSetting _settings;
1613
private readonly IServiceProvider _services;
14+
private readonly IHttpContextAccessor _context;
1715

18-
public TwilioVoiceController(TwilioSetting settings, IServiceProvider services)
16+
public TwilioVoiceController(TwilioSetting settings, IServiceProvider services, IHttpContextAccessor context)
1917
{
2018
_settings = settings;
2119
_services = services;
20+
_context = context;
2221
}
2322

24-
[Authorize]
25-
[HttpGet("/twilio/token")]
26-
public Token GetAccessToken()
27-
{
28-
var twilio = _services.GetRequiredService<TwilioService>();
29-
var accessToken = twilio.GetAccessToken();
30-
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
31-
return new Token
32-
{
33-
AccessToken = accessToken,
34-
ExpireTime = jwt.Payload.Exp.Value,
35-
TokenType = "Bearer",
36-
Scope = "api"
37-
};
38-
}
39-
40-
[HttpPost("welcome")]
23+
/// <summary>
24+
/// https://github.com/twilio-labs/twilio-aspnet?tab=readme-ov-file#validate-twilio-http-requests
25+
/// </summary>
26+
/// <param name="request"></param>
27+
/// <param name="states"></param>
28+
/// <returns></returns>
29+
/// <exception cref="ArgumentNullException"></exception>
30+
[ValidateRequest]
31+
[HttpPost("twilio/voice/welcome")]
4132
public TwiMLResult InitiateConversation(VoiceRequest request, [FromQuery] string states)
4233
{
4334
if (request?.CallSid == null) throw new ArgumentNullException(nameof(VoiceRequest.CallSid));
@@ -48,7 +39,8 @@ public TwiMLResult InitiateConversation(VoiceRequest request, [FromQuery] string
4839
return TwiML(response);
4940
}
5041

51-
[HttpPost("{conversationId}/receive/{seqNum}")]
42+
[ValidateRequest]
43+
[HttpPost("twilio/voice/{conversationId}/receive/{seqNum}")]
5244
public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversationId, [FromRoute] int seqNum, [FromQuery] string states, VoiceRequest request)
5345
{
5446
var twilio = _services.GetRequiredService<TwilioService>();
@@ -88,12 +80,15 @@ public async Task<TwiMLResult> ReceiveCallerMessage([FromRoute] string conversat
8880
}
8981
}
9082
await messageQueue.EnqueueAsync(callerMessage);
91-
response = twilio.ReturnInstructions(null, $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true, 1);
83+
84+
int audioIndex = Random.Shared.Next(1, 5);
85+
response = twilio.ReturnInstructions($"twilio/hold-on-{audioIndex}.mp3", $"twilio/voice/{conversationId}/reply/{seqNum}?states={states}", true, 1);
9286
}
9387
return TwiML(response);
9488
}
9589

96-
[HttpPost("{conversationId}/reply/{seqNum}")]
90+
[ValidateRequest]
91+
[HttpPost("twilio/voice/{conversationId}/reply/{seqNum}")]
9792
public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversationId, [FromRoute] int seqNum, [FromQuery] string states, VoiceRequest request)
9893
{
9994
var nextSeqNum = seqNum + 1;
@@ -151,7 +146,8 @@ public async Task<TwiMLResult> ReplyCallerMessage([FromRoute] string conversatio
151146
return TwiML(response);
152147
}
153148

154-
[HttpGet("speeches/{conversationId}/{fileName}")]
149+
[ValidateRequest]
150+
[HttpGet("twilio/voice/speeches/{conversationId}/{fileName}")]
155151
public async Task<FileContentResult> RetrieveSpeechFile([FromRoute] string conversationId, [FromRoute] string fileName)
156152
{
157153
var fileService = _services.GetRequiredService<IFileStorageService>();

src/Plugins/BotSharp.Plugin.Twilio/Services/TwilioService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ public VoiceResponse ReturnInstructions(string speechPath, string callbackPath,
8181
if (!string.IsNullOrEmpty(speechPath))
8282
{
8383
gather.Play(new Uri($"{_settings.CallbackHost}/{speechPath}"));
84+
if (speechPath.Contains("hold-on-"))
85+
{
86+
int audioIndex = Random.Shared.Next(1, 4);
87+
gather.Play(new Uri($"{_settings.CallbackHost}/twilio/typing-{audioIndex}.mp3"));
88+
}
8489
}
8590
response.Append(gather);
8691
return response;

src/Plugins/BotSharp.Plugin.Twilio/TwilioPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ public void RegisterDI(IServiceCollection services, IConfiguration config)
2323
services.AddSingleton<ITwilioSessionManager>(sessionManager);
2424
services.AddSingleton<TwilioMessageQueue>();
2525
services.AddHostedService<TwilioMessageQueueService>();
26-
26+
services.AddTwilioRequestValidation();
2727
}
2828
}

src/WebStarter/Program.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using BotSharp.Plugin.ChatHub;
55
using Serilog;
66
using BotSharp.Abstraction.Messaging.JsonConverters;
7-
using Python.Runtime;
87

98
var builder = WebApplication.CreateBuilder(args);
109

@@ -42,11 +41,4 @@
4241
.UseBotSharpOpenAPI(app.Environment)
4342
.UseBotSharpUI();
4443

45-
Runtime.PythonDLL = @"C:\Users\xxx\AppData\Local\Programs\Python\Python311\python311.dll";
46-
PythonEngine.Initialize();
47-
PythonEngine.BeginAllowThreads();
48-
49-
app.Run();
50-
51-
// Shut down the Python engine
52-
PythonEngine.Shutdown();
44+
app.Run();

0 commit comments

Comments
 (0)