Scenario: Call is received and caller is placed in a conference using the following code
var response = new TwilioResponse();
response
.Say("Please wait while we attempt to locate the person you were trying to reach.")
.DialConference(string.Format("{0} Waiting Room", digits), new { beep = "false"})
return TwiML(response);
Now I need to Dial out and connect to a mobile users phone and prompt them to accept or send caller to voice mail. I'm assuming once the DialConference is initiate the original caller is placed on hold and no more TwiML is processed. So the only way to initiate a new call is to use the RestAPI.
However I would like to use the .net helper's fluent syntax and it "should" be possible. If you know an example of doing a simultaneous Dial using the fluent syntax, it should also work with the Conference verb.
How do I initiate an outbound call while having a received call put into a conference room, all using TwiML?
Twilio evangelist here.
There isn't a way using only TwiML to put Caller A into the conference, then dial Caller B. With your example above, Twilio will stop executing the TwiML once it hits the Dial and not start again until Caller A leaves the conference.
However, if you just want call screening, then you could check out this HowTo, which shows you how without the conference:
http://www.twilio.com/docs/howto/callscreening
Hope that helps.
Related
As per myunderstanding on masstransit
Publish: Sends a message to subscribers .
Send: Used to send messages in fire and forget fashion
Requests: uses request/reply pattern to just send a message and get a response
In my requirement i need to validate my request before calling the Send method. Here the validation should occur at DB level to check for say duplicate records.
I tried to use publish before my send method , but send method doesnt wait for the publish consumer to execute.
My scenario is if (validation is success) proceed with saving data ie the send request job to save data.
So should i use request response pattern here for doing the validation. I am a newbie to masstransit and microservice.
MyTestController{
if(validation success) // how to validate here
Send request to save data.
}
It sounds like you want to validate the data before it is sent out. Something conceptually like this.
class MyTestController
{
// ..
public async Task<IActionResult> Post(SomeData data)
{
if(DataIsValid(data))
_publishEndpoint.Publish(new Message())
}
}
You can validate the data (like null checking) like any other code before you publish. Nothing special here, so I'm guessing its something else.
You want to validate the data using some other data in a database. If its the same database that the website/api is using - that is also not a special thing, so I'm guessing that is not it either.
You want to, some how, validate the data is correct before sending the message. But that you need to use the data of the application that the message is going to. That is typically where I see people get tripped up.
Assuming its something like number three. Let's call the sending service "Service A" and the receiving service "Service B". Today it sounds like you are trying to put the validation in "Service A" but it really has to be in "Service B". What I would do is implement a Saga in "Service B". The first step would be to take request (creating an instance of a saga), then validate the data, then if it passes validation, the saga can take the next step that you want in the process. That should give you what you want in terms of validation before action (we just need to move it to "Service B").
Now "Service B" can expose the state of the Saga at an endpoint like /saga-instance/42 where the controller takes the 42, digs into the database, grabs the saga data and converts it into an API response. Service A can poll that endpoint to get updated status details.
Ultimately, I hope you see that there are a lot of variables at play, but that there is a path forward. You may have to simply adjust where certain actions are taken.
To set this up, here is the use case:
IVR system calls someone and reads a long-ish twiml prompt at them (about 251 characters)
at the end of the prompt gather user input
if a non-human answers the phone, I'm using asyncAMD callback to get the result of AMD and then leave a voice message
I am currently placing an outbound call using this code:
var call = CallResource.Create(
machineDetection: "DetectMessageEnd",
asyncAmd: "true",
asyncAmdStatusCallback: new Uri("[URI to callback]"),
asyncAmdStatusCallbackMethod: HttpMethod.Post,
twiml: new Twilio.Types.Twiml("<Response><Say>[MyMessage]</Say></Response>"),
from: new Twilio.Types.PhoneNumber(configuration["fromPhoneNumber"]),
to: new Twilio.Types.PhoneNumber(configuration["toPhoneNumber"])
);
where "MyMessage" is about 251 characters long.
The answering machine bit works wonderfully, and I'm able to leave a voice message in case a non-human answers (see my question and subsequent answer for How to leave a voicemail using Twilio AMD? for details).
However, I cannot for the life of me figure out how to prolong the asyncAMD callback long enough for the initial prompt to be finished in the case a human answers.
I've tried adding all of these optional API tuning parameters, and I still can't get it to work:
machineDetectionTimeout: 59,
machineDetectionSpeechThreshold: 6000,
machineDetectionSpeechEndThreshold: 5000,
machineDetectionSilenceTimeout: 10000,
What are my options here? Bail on asyncAMD and use blocking AMD? I need to be able to leave a voice message in case of a non-human answering, but I need to push the results of the asyncAMD invoking it's callback long enough for the initial response to be read in a human answers.
I'm going to take this approach. In the recipient answers and says "hello" (which is likely they'll say it), answeredBy will return "human", but if they don't and just listen to the initial prompt, I get "unknown" back. At this point, I'm going to treat an answeredBy "unknown" as a person answering and listening to the initial Twiml prompt.
Given client code that makes an outgoing call like this:
var accountSid = configuration["accountSid"];
var authToken = configuration["authToken"];
TwilioClient.Init(accountSid, authToken);
var call = CallResource.Create(
machineDetection: "DetectMessageEnd",
asyncAmd: "true",
asyncAmdStatusCallback: new Uri("[URL]/callback/index"),
asyncAmdStatusCallbackMethod: HttpMethod.Post,
twiml: new Twilio.Types.Twiml("<Response><Say>Ahoy there!</Say></Response>"),
from: new Twilio.Types.PhoneNumber(configuration["fromPhoneNumber"]),
to: new Twilio.Types.PhoneNumber(configuration["toPhoneNumber"])
);
aka, asyncAmd is enabled and callback URL is specified, with my webhook controller action that looks like this:
[ApiController]
[Route("callback")]
public class CallbackController : TwilioController
{
[HttpPost]
[Route("index")]
public IActionResult Index()
{
var response = new VoiceResponse();
if (Request.Form.TryGetValue("AnsweredBy", out var answeredBy))
{
if (answeredBy != "human")
{
response.Say("this is the voice message");
}
}
return Content(response.ToString(), "text/xml");
}
}
why is it there is no voicemail being left?
Note: I am including the Twiml I want to say in CallResource.Create b/c I don't want a callback to get the message contents in case of a human answering.
I only need the callback performed for the results of AMD detection, and then to leave a voice message.
Do I do that with response.Say?
Thanks!
Twilio developer evangelist here.
Twilio answering machine detection can happen in synchronous or asynchronous mode. From this blog post:
With Async AMD on Twilio, AMD is done asynchronously (hence the name). When the call is answered, a call url is executed immediately, so if a person answers the call rather than voicemail, they can begin interacting with your application without any silence. Then “asynchronously”, or “in parallel”, AMD processes the call audio and determines what answered the call. When AMD processing is complete, the result (the AnsweredBy parameter) is sent to a second URL, the asyncAmdStatusCallback.
One key difference between standard AMD and async AMD is how you modify the call once receiving the AMD result. With standard AMD, you have one URL and the result is sent to this URL just like any other outbound-api call. When your URL receives the result, you can check the AnsweredBy parameter and update the call accordingly with TwiML. With Async AMD, your call is already executing TwiML and you instead need to update the call via API.
In your case you are using async AMD, but you are not updating the call via the API.
You have two options. You can choose to use synchronous AMD and you can then respond to the result using TwiML like you are doing so far.
Alternatively, you can continue to use async AMD, but instead of responding to the webhook with TwiML, use the REST API to update the call with the new TwiML or with a new webhook URL.
One thing I would look out for too. Your initial TwiML is very short, your example code shows that it sends <Response><Say>Ahoy there!</Say></Response>. It is entirely possible that this TwiML will be completed before an answering machine is detected and since it is the only TwiML for the call, the call would then hang up. You may want to consider using a longer message or pausing so that you can get the result of the AMD.
Figured I'd follow up here. Thanks #philnash for the help. You were indeed right
I was returning Twiml from the asyncAMD webhook instead of updating the call.
my very short Twiml in the initiating call was not long enough
I got through the first part and things were still failing even with Twiml that was longer:
<Response><Say>Hello there. This is a longer message that will be about as long as the real message asking you to confirm or cancel your appointment. Hopefully it's long enough!</Say></Response>
BUT, that still was not long enough! By the time the asyncAMD callback was invoked, and I tried to use CallResource.Update, the call was already ended.
I ended up dumping about 2,000 characters of lorem ipsum into the outgoing call Twiml and the asyncAMD callback using CallResource.Update worked perfectly.
I am using the following libraries to connect a bot to a Google Pub/Sub endpoint to perform a simple reply to a card click event.
Google.Apis.HangoutsChat.v1 1.34.0.1233
Google.Cloud.PubSub.V1 1.0.0-beta18
When I construct my card, everything looks normal in the UI, including the button that is supposed to raise the event.
The topic and subscription contain the default settings, following the guide here
I found the following information from the Google documentation about retries here
Responding synchronously
A bot can respond to an event synchronously by returning a
JSON-formatted message payload in the HTTP response. The deadline for
a synchronous response is 30 seconds.
A synchronous response from a bot is always posted in the thread that
generated the event to the bot.
After clicking the button, my subscriber receives 3 duplicate events. The events have the correct response with all of the right metadata, but are exact duplicates of each other, including the id of the message itself.
I don't feel there is a necessarily large delay in the response of the bot (it should happen in <1 second for this test), so I am not sure why these messages are being duplicated.
I've also tried setting the thread id for the card when responding (via the Thread property itself, or the ThreadKey property), but I always seem to get a new thread id when I post a message.
var cardMessage = MessageSender.Spaces.Messages.Create(new Message()
{
Space = new Space()
{
Name = inReplyToThisMessage.Space.Name
},
Thread = new Thread()
{
Name = inReplyToThisMessage.Thread.Name
},
Cards = new List<Card>()
{
card
},
}, inReplyToThisMessage.Space.Name);
var sendCardResult = await cardMessage.ExecuteAsync().ConfigureAwait(false);
//Thread id of sendCardResult does not match inReplyToThisMessage.Thread.Name no matter what
Interestingly enough, trying to create a new message in response to the click event causes the bot to display a "Unable to connect to bot. Try again later", but displays 3 new messages. Also, when specifying an arbitrary thread key, this key is never echoed back in the bot's response.
Make sure you are returning the main event method properly. What looks to be happening is that you are making an asynchronous call to the chat, but then the chat is looking for a response from the actual event method itself. Google will traditionally try three times before giving up (even if it doesn't take thirty seconds)
If you are indeed returning the event call correctly after you made your api request, then there is something in your code that is causing the Google Bot to think it is not getting a response, so it tries three times. Since the issue could be multi-faceted I would need to look at how you are accepting and returning the click response.
This bug has finally been fixed by Google.
Brief Idea: I am developing a small social networking kinda site.
Now there's a user "A" who has 100 followers...now what i want to do is whenever user "A" submits an article in the website all his followers should get an email with the article link...that is okay i can do it.
Problem: Now, there's a submit button on the page which stores the article in the DB and sends email to the followers...as there are many followers it takes a lot of time sending the emails...so the page keeps showing loading msg till all the emails are sent..how can i send all the emails asynchronously ??
i mean after the article has been submitted ...the emails should go automatically to the followers without putting the email sending function in the click event of the button....hope am not confusing you folks.
can i do something like store the article in the DB , redirect to the article page , start sending emails in a batch of 10 per 10 mins automatically...this process should start as soon as an article has been submitted by an user.
I had a similar issue with batch emails, and various other long-running tasks.
I developed a window service which contained a job manager. When a job needs to run from the main MVC application, the web application communicates with the service over HTTP (actually, using JSON), and the service performs the meat of actually sending emails, or performing other long-running tasks.
This means the web application request returns immediately.
The web application can also poll the service to determine the status of any particular job that is running (each job is given a unique identifier).
I would create a database table containing information about all pending email notifications.
When hitting submit, you can quickly add rows to this table.
Then, a background thread can check the table and send the mails (and of course remove the successfully sent ones from the table).
Have you thought to implement it using AJAX ?
When the user press on the submit button, instead of posting back to the server, create 2 ajax calls:
The first one is to save the article to the repository (database ?).
After receiving succesfull answer from the server (which can include the article id), invoke 2nd ajax call to send the mails. The server can start a thread to send the mails so the answer to the client will be immediate.
My preferred way of invoking ajax calls is using JQuery:
$.ajax({
type: "POST",
url: "services.aspx/SubmitArticle",
data: "{articlecontent: '[put here the content you want to send]'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function(response) {
// Handle Error here. The response object contains the error details
},
success: function(response) {
// Check here if the article has been saved:
// response.d property contains the server answer. It can be boolean,
// integer, string or any other complex object
// If article saved, invoke here the send mail ajax call. assuming the response.d contains
// the article id:
sendMails(response.d);
// sendMails invokes another ajax similiar to this code snippest
}
});
In the server side the async email send method can looks like:
[WebMethod]
public static bool SendMails(int articleId)
{
// Add the actual method that send mail to the thread pool
ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendMail), articleId);
return true;
}
private void DoSendMail(object a)
{
int articleId = (int)a;
// Your code that sends mails goes here
}
You could use a queueing system like MassTransit, ZMQ or MSMQ.
Or... If you really wanted to create a cool app, you could pass the emailing task to a node.js app!?