Getting Digits from twilio Gather - node.js

I am trying to get the digits entered into phone. I thought res.Digits in Pin function would be the way but I get an undefined error
exports.Say = function(req, res)
{
var resp = new twilio.TwimlResponse();
resp.gather(
{
action:'http://pap-papdemo.rhcloud.com/api/Phone/Pin',
finishOnKey:'#',
method:"POST"
}, function()
{
this.say('Please enter your Phone and Pin number followed by the hash key');
});
//Render the TwiML document using "toString"
res.writeHead(200,
{
'Content-Type':'text/xml'
});
res.end(resp.toString());
};
exports.Pin = function(req, res)
{
var resp = new twilio.TwimlResponse();
console.log("***** PIN *****");
console.log("Pin: Response " + res.body.Digits);
//Render the TwiML document using "toString"
res.writeHead(200,
{
'Content-Type':'text/xml'
});
res.end(resp.toString());
};
any idea what I need to do as I need to store pin number in db

Megan from Twilio here. I saw you answered your own question but figured I'd update as an answer for others who land here.
Twilio will pass Digits as a parameter in addition to the standard TwiML Voice request parameters with its request to the 'action' URL.
Thus var pin = JSON.stringify(req.body.Digits); worked in this case.

Related

Why is my Twilio nodejs transcribing attempt calling the client twice?

It is calling the client twice and making 1 37 second (in twilio dashboard) phonecall with two transcripts one 22 seconds long the other 5 seconds long, anyone have any ideas?
The phonecall when I make a straight phonecall and record lasts 19 seconds. Thats what my transcript should be 19 seconds longs. Its looping around somewhere.
I used real credentials and real phone numbers.
var twilio = require('twilio');
var client = require('twilio')(accountSid, authToken);
const VoiceResponse = require('twilio').twiml.VoiceResponse;
client.calls.create({
url: 'http://107.170.228.177:80/sendT',
to: '+17000000',
from: '+10000000'
})
app.post('/sendT', urlencodedParser, function(req, res) {
console.log('made to send t')
const rt = new VoiceResponse();
rt.record({
transcribe: true,
transcribeCallback: '/rT'
});
res.status(200);
res.send(rt.toString());
console.log('RT string' + rt.toString());
})
app.post('/rT', urlencodedParser, function(req, res) {
console.log('made to receiveT post');
var ttemp = req['body'].TranscriptionText;
console.log('transcription text ' + ttemp);
var masterFile = __dirname + "/master/t.json";
fs.writeFile(masterFile, ttemp, function(err) {}) //
res.status(200);
res.send();
});
NodeJS output
RT string<?xml version="1.0" encoding="UTF-8"?><Response><Record transcribe="true" transcribeCallback="/rT"/></Response>
made to send t
RT string<?xml version="1.0" encoding="UTF-8"?><Response><Record transcribe="true" transcribeCallback="/rT"/></Response>
made to send t
RT string<?xml version="1.0" encoding="UTF-8"?><Response><Record transcribe="true" transcribeCallback="/rT"/></Response>
made to receiveT post
*call transcript*
made to receiveT post
*call transcript*
Twilio developer evangelist here.
What is happening here is very specific to the <Record> TwiML that you are using.
When the recording is finished being made, Twilio will make an HTTP request to the action attribute that you set on the <Record> to see what to do with the call now. In the case of no action attribute, Twilio will make that request to the current document URL, that is your /sendT endpoint in this case.
This is what it causing the loop, the <Record> then appears again to Twilio and times out after 5 seconds, at which point the call is decided to be over. Now you get two recordings, including 5 seconds of silence.
To fix this, you should either add an action attribute that points to an endpoint that just returns the TwiML to <Hangup/>.
app.post('/sendT', urlencodedParser, function(req, res) {
const rt = new VoiceResponse();
rt.record({
transcribe: true,
transcribeCallback: '/rT',
action: '/hangup'
});
res.status(200);
res.send(rt.toString());
})
app.post('/hangup', function(req, res) {
const hangup = new VoiceResponse();
hangup.hangup();
res.status(200);
res.send(hangup);
})
Or, you can keep no action URL and just check the request to see if it has already made a recording and hang up conditionally based on that.
app.post('/sendT', urlencodedParser, function(req, res) {
const rt = new VoiceResponse();
if (typeof req.body.RecordingUrl !== 'undefined') {
rt.hangup();
} else {
rt.record({
transcribe: true,
transcribeCallback: '/rT',
action: '/hangup'
});
}
res.status(200);
res.send(rt.toString());
})
Let me know if this helps at all.

How can I alter a call that's in progress with Twilio & NodeJs

Here are the steps that I'd like to accomplish:
Call, and eventually text, my Twilio number
Gather a number to call.
Create and move my current call into a conference call.
Call the gathered number.
Add the called number into the conference with me.
Currently I can call my Twilio number, gather a number to be called, create a conference call - but where I'm getting lost is calling the gathered number as well as adding them into the conference I created.
app.post('/call', function(req, res) {
var twiml = new twilio.TwimlResponse();
res.type('text/xml');
if (req.body.From === '+15555555555) {
twiml.gather({
action: '/call/initiate',
finishOnKey: '#',
numDigits: '10',
timeout: '5'
}, function() {
this.say('Enter your number', {
voice: 'man'
});
});
}
else {
twiml.redirect(VOICEMAIL_TWIMLET_OF_CHOICE);
}
res.send(twiml.toString());
});
// Initiate a call from text
app.post('/call/initiate', function(req, res) {
// Create new Twiml response
var twiml = new twilio.TwimlResponse();
// Phone number to call and add to conference
var to = req.body.Digits;
// Create random conference name
var conferenceName = Math.floor(Math.random() * 10000).toString();
// Add myself to the conference call
twiml.dial((node) => {
node.conference(conferenceName, {
startConferenceOnEnter: true,
record: true,
beep: 'true'
});
});
// Redirect twiml to a new url
// Send conferenceName & Number
twiml.redirect('/join_conference?id=' + conferenceName + '&number=' + to);
res.set('Content-Type', 'text/xml');
res.send(twiml.toString());
});
// Call and add caller to conference
app.post('/join_conference', (req, res) => {
var conferenceName = req.query.id;
var to = '+1' + req.query.number;
// Create new Twiml response
var twiml = new twilio.TwimlResponse();
// Call and add user to conference call
twiml.dial(to, (node) => {
node.conference(conferenceName, {
startConferenceOnEnter: true,
});
});
console.log('call called');
res.set('Content-Type', 'text/xml');
res.send(twiml.toString());
});
After I enter the digits and hit the finishOnKey I automatically hear the waiting music. However, at that point - the app just hangs and a call isn't placed.
Twilio developer evangelist here.
The issue is that the TwiML you return to your /call/initiate endpoint is just for the first leg of your call, you can't create another call leg with TwiML alone.
However, you can use the Twilio REST API to generate the second leg of the call within the same request. Here's an updated endpoint that you can use instead:
app.post('/call/initiate', function(req, res) {
// Create new Twiml response
var twiml = new twilio.TwimlResponse();
// Phone number to call and add to conference
var to = req.body.Digits;
// Create random conference name
var conferenceName = Math.floor(Math.random() * 10000).toString();
// Add myself to the conference call
twiml.dial((node) => {
node.conference(conferenceName, {
startConferenceOnEnter: true,
record: true,
beep: 'true'
});
});
// Make call to the other party
// Send conferenceName as part of the URL
var client = new twilio(YOUR_ACCOUNT_SID, YOUR_AUTH_TOKEN);
client.calls.create({
from: YOUR_TWILIO_NUMBER,
to: '+1' + to,
url: 'https://example.com/join_conference?id=' + conferenceName
});
res.set('Content-Type', 'text/xml');
res.send(twiml.toString());
});
Then your '/join_conference' endpoint need only dial the caller into the conference room, like so:
app.post('/join_conference', (req, res) => {
var conferenceName = req.query.id;
// Create new Twiml response
var twiml = new twilio.TwimlResponse();
// Call and add user to conference call
twiml.dial((node) => {
node.conference(conferenceName, {
startConferenceOnEnter: true,
});
});
console.log('call called');
res.set('Content-Type', 'text/xml');
res.send(twiml.toString());
});
Let me know if that helps at all.
Edit: The comment said it still wasn't calling the other party. Let's take a look more closely at the command to call the other side. The call to create will return a Promise, so we can see what happens and whether it is succeeding or failing (and why).
var client = new twilio(YOUR_ACCOUNT_SID, YOUR_AUTH_TOKEN);
client.calls.create({
from: YOUR_TWILIO_NUMBER,
to: '+1' + to,
url: 'http://example.com/join_conference?id=' + conferenceName
}).then(function(call) {
console.log(call.sid);
}).catch(function(err) {
console.error("Something went wrong creating the call.");
console.error(err);
});
Try updating the code to that and see what happens. If there is an error, I'm sure it will help you solve this.

twilio say something to caller (node.js)

Hey guys I am working on something and have following Problem :
ACTUAL AIM - If someone calls, I want to let the voice say: "Try to reach someone" and then call some numbers out of an array. ( cant do that atm because i need to fake a call )
ATM AIM - Thats why I at least want to say something to the one who answers the twilio call, that I can be sure it "would" work.
So i faked a call by sending the url that twilio would send (if it gets a call) via a localhost http server. So far so good, my phone gets called. But the woman dont say what I wanted her to say... She sais : Thank you for trying our documentation and then waiting music is following.
AND: The call.status is ALLWAYS queued, or I dont catch it at the right place :/ , Remember my phone is ringing so it should have at least the status ringing ...
This is what I have at the moment:
requestHandler.js:
var querystring = require("querystring");
var emergency = require("./emergency");
var twilio = require('twilio');
function callRequest(response) {
var resp = new twilio.TwimlResponse();
resp.say({voice:'woman'}, 'ahoy hoy! Testing Twilio and node.js');
console.log("call incomming ! EMERGENCY 1 1 11 !");
//emergency.handleIncommingCall();
response.writeHead(200, {"Content-Type": "text/xml"});
response.end(resp.toString());
}
exports.callRequest = callRequest;
server.js:
var http = require("http");
var url = require("url");
function start(route, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(handle, pathname, response, request);
}
http.createServer(onRequest).listen(1337);
console.log("Server has started");
}
exports.start = start;
exports.http = http;
router.js:
function route(handle, pathname, response, request) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](response, request);
}else{
console.log("No request handler found for " + pathname);
response.writeHead(404, {"Content-Type": "text/html"});
response.write("404 Not found");
response.end();
}
}
exports.route = route;
index.js:
var server = require("./server");
var router = require("./router");
var requestHandler = require("./requestHandler");
var handle = { };
handle["/demo.twilio.com/welcome/voice/"] = requestHandler.callRequest;
server.start(router.route, handle);
emergency.js:
var twilio = require('twilio');
var accountSid = 'cant tell ya';
var authToken = "cant tell ya";
var client = require('twilio')(accountSid, authToken);
var firstCascadeNumber = "cant tell ya";
var secondCascadeNumber;
var privateNumber; //enter privateNumber here
var twiml = new twilio.TwimlResponse();
function handleIncommingCall (){
//twilio should say : we contact team internet pls wait
//twilio should make music
call(1,firstCascadeNumber);
//cb if staus ist nicht rangegangen call(2)
}
function call (cascade,cascadeNumber){
client.makeCall({
url: "http://demo.twilio.com/docs/voice.xml",
to: cascadeNumber,
from: "cant tell ya"
}, function(err, call) {
if(err){
console.log("ERROR:", err.message);
}else{
console.log("calling " + cascadeNumber);
console.log("status: " + call.status);
if(cascade == 1){
//twiml.say("Hello this i a test. Thank you for calling.");
console.log("should say what i want it to say ! god damn it ");
console.log("status: " + call.status);
//if user geht ran
//startConference()
//if user geht nicht ran
//call(2,secondCascadeNumber)
}else if(cascade == 2){
//if user geht ran
//startConference()
//if user geht nicht ran
//inform caller that no one is there
}else{
console.log("Error: cascade doesnt exsist");
}
}
});
}
function openConference(call,from,to){
//call.joinConference([roomName, option, cbOnEnd])
}
exports.handleIncommingCall = handleIncommingCall;
Twilio developer evangelist here.
You're most of the way there, but you've not quite set your application out right here.
When you make the call, the callback you get only refers to whether the call started correctly. It is not a callback that you need to return TwiML to in order to tell Twilio what to do with the call.
Instead, what happens is when Twilio makes the call, it will send an HTTP request to the URL you supply when you make the call in the first place. That URL should be in your application and available to Twilio.
This blog post on using Twilio with Node.js should be able to show you what I mean by all of that and set you up with a good way of testing this locally too.
Edit
Thanks for updating your code.
Your problem is that you are not telling Twilio to ask you what to do with the call once it connects.
When you create a call with the API you need 3 parameters, the number to call, the number to call from and a URL. When Twilio connects the call it will make an HTTP request to the URL you supply asking what to do next and this is where you supply some TwiML to tell Twilio what to do with the call.
Currently you are supplying this URL: http://demo.twilio.com/docs/voice.xml
If you click through the demo Twilio URL there, you will see the TwiML that is being returned and why you hear a message you are not expecting. Because the URL is not yours, your application cannot take control of the call.
You need to send a URL that points at a route in your application, and that route needs to respond with the TwiML you want. You can expose your local server to Twilio using a tool called ngrok which will allow you to test this.
I recommend you follow the tutorial I linked before, this tutorial on using ngrok to text your incoming HTTP requests from Twilio and this tutorial on creating a click to call application with Twilio.
In the case of your application, instead of trying to handle "/demo.twilio.com/welcome/voice/" which is not a URL you have control of, you should handle, say:
var handle = { };
handle["/calls"] = requestHandler.callRequest;
and then use ngrok to create a tunnel to your application and pass the URL to client.makeCall like this:
function call (cascade,cascadeNumber){
client.makeCall({
url: "http://YOUR_NGROK_SUBDOMAIN.ngrok.io/calls",
to: cascadeNumber,
from: "cant tell ya"
}, function(err, call) {
if (err) {
console.log("Call could not be made", err);
} else {
console.log("Call created successfully. Call ID:", call.sid);
}
}
}
Let me know if that helps.

Twilio conference call with nodejs

I want to develop a conference application using Twilio and Nodejs.
In my application first person get a call from twilio number after that first person who received the call need to create a conference and call to another person for joining the same conference room. I have created below code but it is not working.
app.post('/callcenter', function(req, res) {
var twiml = new twilio.TwimlResponse();
client.makeCall({
to : config.twilio.to, // Any number Twilio can call
from : config.twilio.from, // A number you bought from Twilio and can use for outbound communication
url : 'http://example.com/createconf' // A URL that produces an XML document (TwiML) which contains instructions for the call
}, function(err, responseData) {
console.log(responseData.from); // outputs "+14506667788"
if (err) {
response.status(500).send(err);
} else {
res.type('text/xml');
res.send(twiml.toString());
console.log(twiml.toString());
}
});
});
app.post('/createconf', function(req, res) {
var twiml = new twilio.TwimlResponse();
console.log('Inside createconf');
.gather({
action:'http://exampl.com/enterinconf',
finishOnKey:'*',
numDigits:'1',
timeout:'20'
}, function() {
this.say('Press 1 for moderator')
.say('Press 2 for speak');
})
res.type('text/xml');
res.send(twiml.toString());
console.log(twiml.toString());
});
app.post('/enterinconf', function(req, res) {
var twiml = new twilio.TwimlResponse();
client.makeCall({
to : config.twilio.modfwd, // Any number Twilio can call
from : config.twilio.from, // A number you bought from Twilio and can use for outbound communication
url : '../conference/moderatorconf.xml' // A URL that produces an XML document (TwiML) which contains instructions for the call
}, function(err, responseData) {
console.log(responseData.from);
if (err) {
response.status(500).send(err);
} else {
res.type('text/xml');
res.send(twiml.toString());
console.log(twiml.toString());
}
});
});
Can somebody help me on this how I can develop a conference call in Nodejs with twilio.

how to receive and process a photo mms using twilio

Looking for an example, of how to receive and process images via mms to my app using Twilio.
Looking at the number configuration screen in the twilio dashboard, I assume that I set up an incoming phone number and a HTTP POST url to send incoming mms to. However, I'm not sure what gets posted to that url and don't know the structure of that data.
Does someone have an example of what data gets POSTed to the url and in what format? Any javascript examples of what data the server would process would be great.
Firstly use the twilio-node module(npm install twilio). Once you have that in place, you can just access the webhook request body like you would any request body req.body.
As depicted in twilio's docs, the structure is like so:
{
MessageSid: String, //ID pertaining to this message
AccountSid: String, //ID pertaining to your twilio account
From: String, //phone number of sender
To: String, //recipients phone number, you in this case
Body: String, //Message body
NumMedia: Number, //number of attached media
//these values only appear when media is present(NumMedia.length > 0)
MediaContentType: [String] //type of content in SMS
MediaUrl: [String] //URL to download the media
}
You can then do something like this using the twilio modules, caolan/async module, and the popular request/request module:
var twilio = require('twilio'),
fs = require('fs'),
async = require('async'),
request = require('request');
app.post('/mms', function(req, res) {
var options = { url: 'https://subtle-gradient-188.herokuapp.com/twiml' };
if (!twilio.validateExpressrequire(req, 'YOUR_TWILIO_AUTH_TOKEN', options)) return res.status(401).send("Bad key!");
if(!req.body.hasOwnProperty('MediaUrl')) return res.send("Missing media...");
var media = req.body.MediaUrl;
//download all media
async.map(media, download, function(err, filenames) {
var resp = new twilio.TwimlResponse();
if(err) {
resp.say("Problem occured");
console.log(err);
}
else resp.say('Files recieved: ' + filenames.join(', '));
res.type('text/xml');
res.send(resp.toString());
});
});
//download a single url to a unique filename
function download(url, cb) {
var name = Date.now() + url.split('/').pop();
request
.get(url)
.on('error', cb)
.on('end', function() {
cb(null, name);
})
.pipe(fs.createWriteStream(name));
}

Resources