3

My use case:

My case is that i'm making a bot for listening podcast in which user will make call to twilio number and bot will ask what type of podcast would you like to listen then record for 10 seconds

when recording finish, it say user to please wait while we are finding podcast

I want that recording in my webhook so i will figure out caller mood and find appropriate podcast mp3 file from my database and play to caller

Issue I'm Facing:

I'm getting empty body in all of my webhooks

My code:

var express = require("express");
var bodyParser = require("body-parser");
var VoiceResponse = require('twilio').twiml.VoiceResponse;

var app = express();
var port = (process.env.PORT || 4000);

app.use(bodyParser.json())

// helper to append a new "Say" verb with alice voice
function say(text, twimlRef) {
    twimlRef.say({ voice: 'alice' }, text);
}
// respond with the current TwiML content
function respond(responseRef, twimlRef) {
    responseRef.type('text/xml');
    responseRef.send(twimlRef.toString());
}

app.post("/voice", function (request, response, next) {
    console.log("request: ", request.body); //body is comming as empty object

    var phone = request.body.From;
    var input = request.body.RecordingUrl;
    var twiml = new VoiceResponse();
    console.log("phone, input: ", phone, input);

    say('What type of podcast would you like to listen. Press any key to finish.', twiml);
    twiml.record({
        method: 'POST',
        action: '/voice/transcribe',
        transcribeCallback: '/voice/transcribe',
        maxLength: 10
    });

    respond(response, twiml);
});

app.post("/voice/transcribe", function (request, response, next) {
    console.log("request: ", request.body); //body is comming as empty object

    var phone = request.body.From;
    var input = request.body.RecordingUrl;
    var twiml = new VoiceResponse();

    var transcript = request.body.TranscriptionText;    
    console.log("transcribe text: ", transcript);

    //here i will do some magic(Ai) to detect user mood and find an 
    //appropriate mp3 file from my database and send to twilio

    var mp3Url = 'https://api.twilio.com/cowbell.mp3'

    say('start playing.', twiml);
    twiml.play(mp3Url);

    respond(response, twiml);
});

app.listen(port, function () {
    console.log('app is running on port', port);
});

API Test with postman:

enter image description here

enter image description here

added url as webhook on twilio:

enter image description here

Heroku Logs:

enter image description here

Inzamam Malik
  • 3,238
  • 3
  • 29
  • 61
  • rather than request.body, you should try to display first request object. what it returns then you can get idea further. also try to console.log response once. – Rupal Javiya May 09 '17 at 05:47
  • I tried It, It's a very very large object but nothing in it – Inzamam Malik May 09 '17 at 05:49
  • in postman I can see its https request, in your original code, have you checked about this protocol? either its http OR https? also do you have value set in input, phone (parameters you are using in form post)? – Rupal Javiya May 09 '17 at 05:54
  • about https: heroku handle it, i used heroku many times nut never put my head in 's' part of https – Inzamam Malik May 09 '17 at 05:56
  • according to this [document](https://www.twilio.com/docs/api/twiml/record) it should give me these params in POST request body – Inzamam Malik May 09 '17 at 05:58
  • just added one more screenshot in which i added url as webhook in twilio number – Inzamam Malik May 09 '17 at 06:06
  • Shouldn't the call to your /voice URL be a GET instead of a POST? I think Twilio is doing a GET and your code is expecting a POST – Andy May 09 '17 at 18:49
  • twilio is doing POST request of course, you can see it in logs – Inzamam Malik May 09 '17 at 18:56

1 Answers1

9

Twilio developer evangelist here.

You are using body-parser which is good. However, you are using the JSON parser. Twilio makes requests in the format of application/www-x-form-urlencoded so you should change:

app.use(bodyParser.json())

to

app.use(bodyParser.urlencoded({ extended: false }))

Then you should see the parsed body as part of the request.body object.

As an extra note, the transcribeCallback is sent asynchronously to the call. So returning TwiML in response to that request won't affect the call at all. You will need to modify the call in flight, by redirecting it to some new TwiML when you get the result of transcription. An example of updating a call with Node.js is below:

const accountSid = 'your_account_sid';
const authToken = 'your_auth_token';
const client = require('twilio')(accountSid, authToken);

client.calls('CAe1644a7eed5088b159577c5802d8be38')
  .update({
    url: 'http://demo.twilio.com/docs/voice.xml',
    method: 'POST',
  })
  .then((call) => console.log(call.to));
Max Phillips
  • 6,991
  • 9
  • 44
  • 71
philnash
  • 70,667
  • 10
  • 60
  • 88
  • can you please this link " modify the call in flight, by redirecting it to some new TwiML" link of nodejs instead of rest api – Inzamam Malik May 19 '17 at 16:33
  • You mean like this example: https://www.twilio.com/docs/api/rest/change-call-state?code-sample=code-redirect-a-running-call-to-a-new-url&code-language=js&code-sdk-version=3.x – philnash May 19 '17 at 16:36
  • no, i understand how to modifycall using rest api, but i dont want to do it using rest api, i want to do it with 'nodejs twilio sdk' – Inzamam Malik May 19 '17 at 16:42
  • give me any link which demonstrate how to modify call using nodejs sdk – Inzamam Malik May 19 '17 at 16:42
  • 1
    The Node.js SDK uses the REST API to modify calls. It's the only way you can modify a call outside of TwiML. I added the example Node code to the bottom of my answer. – philnash May 19 '17 at 16:45
  • please also have a look of this question, i'm sure you have answer of this: http://stackoverflow.com/questions/44075338/how-to-play-and-record-voice-at-same-time-in-twilio – Inzamam Malik May 19 '17 at 16:57
  • 1
    For express 4.16+, following will work: `app.use(express.json()) app.use(express.urlencoded({extended: true}))` – Zolbayar Apr 13 '19 at 03:00