Twilio Function Read Multiple Speech Input - c#

The use case is the call an IVR system using programmable voice in twilio. Based the IVR question, send answers using twilio function and TWIML. How can I achieve this? So far I have made call using Twilio and refer below the callback webhook.
[HttpPost]
public TwiMLResult Index(string message)
{
var response = new VoiceResponse();
var gather = new Gather(input: new List<Gather.InputEnum>()
{
Gather.InputEnum.Speech
} ,
timeout: 5, action:new Uri("https://url-sample/GatherSample"));
gather.Say("Please press 1 or say sales for sales.");
response.Append(gather);
LogWriter.Debug($"Message : {response.ToString()}");
return new TwiMLResult(response);
}
Also Twilio Function Code.
exports.handler = function(context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
const command = event.SpeechResult.toLowerCase();
twiml.say(`You said ${command}. I'll give you a ${command} fact.`);
callback(null, twiml);
};

Related

Caller doesn't connect into the conference

I'm trying to use Twilio to connect workers through a kind of Walkie Talkie (all the workers get a JWT to make browser calls using the Javascript SDK), for this I use the Twiml verb conference, when the worker press the conference button in the browser it sends a list of the active workers (except for the one who started the conference), I use the callSid as the name of the conference to make it unique and the CallResource to put every worker into the conference.
However, the workers in the list start listening the wait music for a conference room, but the caller automatically end the connection as soon as it is open, it doesn't even ends the conference, I don't know what's wrong with the code, I'm following the documentation for conferences in https://www.twilio.com/docs/voice/twiml/conference
Here is the method that's called when a conference needs to be created:
public VoiceResponse ConferenceTalk(List<string> recipients, string caller, string callSid)
{
TwilioClient.Init(my_account_sid, my_auth_token);
var confName = $"wt_{callSid}";
foreach (var recipient in recipients)
{
CallResource.Create(
url: new Uri($"{this.publicUrl}/Conference/WtConference/{confName}"),
to: new Twilio.Types.Client($"client:{recipient}"),
from: new Twilio.Types.Client(caller));
}
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference(confName,
startConferenceOnEnter: true,
endConferenceOnExit: true);
response.Append(dial);
return response;
}
Here is the endpoint the CallResource target with the url attribute:
[HttpPost]
public TwiMLResult WtConference()
{
var confName = Request.Url.Segments[Request.Url.Segments.Length - 1];
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference(confName);
response.Append(dial);
return TwiML(response);
}
I feel like the time all of this takes to happen might be causing your issues here. And the Twilio Voice SDK may not be the best product for this. I'd have to see maybe a video showing how the interaction works to fully commit to this.
In the meantime, I might try to speed up people joining the conference by sending the TwiML for the conference in the API call, not waiting for the webhook. e.g.:
public VoiceResponse ConferenceTalk(List<string> recipients, string caller, string callSid)
{
TwilioClient.Init(my_account_sid, my_auth_token);
var confName = $"wt_{callSid}";
var outboundResponse = new VoiceResponse();
var outboundDial = new Dial();
outboundDial.Conference(confName);
outboundResponse.Append(outboudDial);
foreach (var recipient in recipients)
{
CallResource.Create(
twiml outboundResponse,
to: new Twilio.Types.Client($"client:{recipient}"),
from: new Twilio.Types.Client(caller));
}
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference(confName,
startConferenceOnEnter: true,
endConferenceOnExit: true);
response.Append(dial);
return response;
}
I say that Twilio Voice might not be best for this because on the Twilio back end, this is going through a whole stack that is built for making phone calls. Outbound calls are made at a rate of 1 call per second, so that might be slowing the calling of your list down.
You could consider the Twilio Video SDK for this instead (you can make audio only calls with the Twilio Video product). For this you would need to be able to trigger each of workers joining a room that was then used to distribute the audio. There aren't limits on calls per second, workers would just need to connect to a room and your application would be able to control who could talk at any one time.

Twilio MVC , how do i make phone number/message dynamic

I am using Visual studio. This is for Asp.net web application (.net framework)
this solution as a webcore application is acceptable as well.
I would like to be able to enter the information for message and to phone number dynamically , but i dont know how to "pause" the program so that this can happen. I understand the dynamic part, and can use Javascript to do that,
Basically what I want is an app that brings up a webpage where the end user enters the to number and the message, and then clicks send to send.
I thought it would be simple, but not so much :(
I have the quick start code for C# as -
// Install the C# / .NET helper library from twilio.com/docs/csharp/install
using System;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
class Program
{
static void Main(string[] args)
{
// Find your Account Sid and Token at twilio.com/console
const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const string authToken = "your_auth_token";
TwilioClient.Init(accountSid, authToken);
var message = MessageResource.Create(
body: "Join Earth's mightiest heroes. Like Kevin Bacon.",
from: new Twilio.Types.PhoneNumber("+15017122661"),
to: new Twilio.Types.PhoneNumber("+15558675310")
);
Console.WriteLine(message.Sid);
}
}
Okay I'm going to assume you want to send SMS. Further, I'm going to assume you're using Asp.Net MVC. Twilio voice is a little bit more complex, as Twilio calls back several times to get voice scripts and update statuses. More complex if you need phone tree behavior.
SMS Callbacks happen more than once too, but they're calling the same callback URL over and over, nothing fancy there.
The flow should look like this:
Web interface -> Asp.Net MVC Controller Action -> Database -> Twilio
I'll leave the web interface to you, and give some examples of the backend stuff.
You'll want a database, with one table 'Message'
Message should have these columns (at a minimum, you may need more):
message_id_pk
twilio_sid (nullable)
message_content (160 character limit if you want to keep messages in one SMS segment, this has considerations on operating cost)
status (nullable)
recipient_phone
Controller Action:
[Authorize] //assuming you'll want to have users authenticate before they can send the sms
[RequireHttps]
public async Task<ActionResult> SendSMS(
[Bind(Include = "message_id_pk, message_content, recipient_phone"] Message message)
{
db.Messages.Add(message);
TwilioSmsSender.SendSMS(message);
return RedirectToAction("Success");
}
And in TwilioSender.cs
public static void SendSMS(Message message)
{
const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const string authToken = "your_auth_token";
TwilioClient.Init(accountSid, authToken);
var message = MessageResource.Create(
body: message.message_content,
from: new Twilio.Types.PhoneNumber("+15017122661"), //note: you can let your Twilio Messaging service handle the phone number, I recommend you look into that
to: new Twilio.Types.PhoneNumber(message.recipient_phone)
statusCallback: new Uri(TwilioCallBackController.SMSCallBackURL)
);
message.twilio_sid = message.Sid;
db.SaveChanges();
}
And in TwilioCallBackController.cs (You need to handle callbacks from Twilio here)
[ValidateTwilioRequest]
public ActionResult TwilioSMSCallback()
{
string sid = Request.Form["SmsSid"];
List<Message> msg = db.Message.Where(x=> x.twilio_sid == sid).ToListAsync();
if(msg.Count > 0)
{
Message message = msg.First();
message.status = Request.Form["SmsStatus"];
}
}

Sending a message to my bot using the Direct Line v3.0 NuGet package

I am trying to use the Direct Line v3.0 NuGet package to send a message to my bot. I am following the sample on Github, but I'm not getting the behavior I expect.
Here is the sample code:
DirectLineClient client = new DirectLineClient(directLineSecret);
var conversation = await client.Conversations.StartConversationAsync();
while (true)
{
string input = Console.ReadLine().Trim();
if (input.ToLower() == "exit")
{
break;
}
else
{
if (input.Length > 0)
{
Activity userMessage = new Activity
{
From = new ChannelAccount(fromUser),
Text = input,
Type = ActivityTypes.Message
};
await client.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
}
}
}
And here is my code:
var directLineSecret = "MY_SECRET";
var client = new DirectLineClient(directLineSecret);
var conversation = await client.Conversations.StartConversationAsync();
var testActivity = new Activity
{
From = new ChannelAccount(name: "Proactive-Engine"),
Type = ActivityTypes.Message,
Text = "Hello from the PCE!"
};
var response = await client.Conversations.PostActivityAsync(conversation.ConversationId, testActivity);
I'm logging all the messages my bot receives. I can talk to the bot at its endpoint on Azure using the Bot Emulator, so I have confidence that it's working through the web chat API. However when I run the code above, the bot logs only a conversationUpdate message. The message I send does not get logged, and the value of response is null.
I'm hoping someone can help me find out where I'm going wrong here. Thanks!
Look at how the demo instantiates ChannelAccount:
new ChannelAccount(fromUser)
Then look at the ChannelAccount constructor signature:
public ChannelAccount(string id = null, string name = null)
This means that fromUser is passed as id. But look at how you instantiated ChannelAccount:
new ChannelAccount(name: "Proactive-Engine")
That code doesn't pass an id, it passes a name. So, you can change it like this:
new ChannelAccount("Proactive-Engine")
If your chatbot needs the name, then instantiate like this:
new ChannelAccount("MyChatbotID", "MyChatbotName")

Twilio - Call Forwarding

I am building an application where a user will call my Twilio Number. After connecting, Twilio will call another user and connect the two parties. However, the number displayed for the second party should be Twilio's number (or no caller ID), not the user's number.
I tired adding SIP header such as privacy = full & p-asserted-identity="anonymous" but none is working.
Code I am using for the callback:
[HttpPost]
public async Task<ActionResult> Connect(string from, string to)
{
//var outgoingPhoneNumber = await GatherOutgoingPhoneNumberAsync(from, to);
var response = new TwilioResponse();
response.Say("Please wait while we contact the other party");
response.Dial("+14085993263", new { });
return TwiML(response);
}
Is there anyway to do that?
Twilio developer evangelist here.
You're very close to the solution, but what want to do is add a callerid attribute to the Dial verb. That way, you can either add your Twilio number, or your own business' verified number. To do that just change your code to the following:
[HttpPost]
public async Task<ActionResult> Connect(string from, string to)
{
var response = new TwilioResponse();
response.Say("Please wait while we contact the other party");
response.Dial("+14085993263", new { callerId = "+1234567890" });
return TwiML(response);
}
Make sure you replace callerId with the number you wish to use. The caller ID can only be one of your Twilio numbers or a verified number as stated above.
Hope this helps you

Using twilio c# client to pass twilio response back

I am using the twilio c# wrapper and am able to receive communication from twilio. I am having trouble responding back to twilio with a response and having twilio recognize it. Currently I am trying to respond with a TwilioResponse. Anyone have a good example? This is a WebApi self hosted windows service.
ex. TwilioResponse().Message("ok");
I have used Same web API you can use the below menioned code but First you have to configure your APP in Twilio UserAccount.
public class WelcomeController : ApiController
{
public HttpResponseMessage Post(VoiceRequest request)
{
var response = new TwilioResponse();
response.Say("Welcome to Dhaval demo app. Please enter your 5 digit ID.");
response.Gather(new { numDigits = 5, action = string.Format("/api/Authenticate") });
return this.Request.CreateResponse(HttpStatusCode.OK, response.Element, new XmlMediaTypeFormatter());
}
}
When I press the 5 digit no then it will lend to Authetication Controller it' look like
public HttpResponseMessage Post(VoiceRequest request)
{
var response = new TwilioResponse();
var validIds = new List<string> { "12345", "23456", "34567" };
var userId = request.Digits;
var authenticated = validIds.Contains(userId);
if (!authenticated)
{
response.Say("You entered an invalid ID.");
response.Hangup();
}
else
{
response.Say("ID is valid.");
response.Redirect(string.Format("/api/Name?userId={0}", userId));
}
return this.Request.CreateResponse(HttpStatusCode.OK, response.Element, new XmlMediaTypeFormatter());
}
and it's work fine in my side, once again check it properly you have given the correct AuthToken
Cheers
After tinkering for a while, this seems to do the trick.
var twiml = new TwilioResponse().Message("test");
return TwilioResponse(twiml);
private HttpResponseMessage TwilioResponse(TwilioResponse twilioResponse)
{
return new HttpResponseMessage()
{
Content = new StringContent(twilioResponse.ToString(), Encoding.UTF8, "text/xml"),
StatusCode = System.Net.HttpStatusCode.OK
};
}

Categories

Resources