Why is my Twilio nodejs transcribing attempt calling the client twice? - node.js

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.

Related

How to evaluate API response from server and act accordingly at client side using Fetch() and Node.js

I fetch data at server side and push the result to global variable and then send that global variable to client with app.post method using Express.js. My problem is that client fetches the global variable too soon without the data received from the API first. How can I evaluate the response so that client would wait the global variable to reveive data first before displaying anything.
Server side, code looks something like this:
let sharpe = ''
app.post('/api', async(req, res, next) => {
console.log('I got a request!')
thisOne = req.body.stock1
thisOne2 = req.body.stock2
var result = await setup();
res.json({
status: 'success',
stocks: sharpe
});
})
Sharpe is the global variable storing the response from multiple API calls and is the one that should be sent back to client. Client side code is this:
const sendData = async (event) => {
event.preventDefault();
var stock1 = document.getElementById('weight1').value
var stock2 = document.getElementById('weight2').value
const data = {stock1, stock2};
const options = {
method: 'POST',
body: JSON.stringify(data),
headers: {'Content-Type': 'application/json' }
}
fetch('/api', options).then(res => res.json()).then(res => {
console.log(res.stocks);
})
}
As a result SendData() function fetches the sharpe variable that is empty at the moment. How can I adjust client side code or server side code that the client waits for a correct response? Thanks.
One solution would be to store the API results to database and client would fetch ready made datastream but is there more straightforward solution?
To wait for your API Server to set the sharpe Parameter, it needs to be awaited, which you already did. It depends on the setup function (for example setup()) which fills the sharpe parameter. It has to return a promise, which is resolved once sharpe is filled with the data.
let sharpe = ''
async setup() {
return new Promise((resolve, reject) => {
sharpe = 'test';
// set value for sharpe
resolve()
})
}
app.post('/api', async(req, res, next) => {
console.log('I got a request!')
thisOne = req.body.stock1
thisOne2 = req.body.stock2
var result = await setup();
res.json({
status: 'success',
stocks: sharpe
});
})
Eventually it starded working when I pushed all the API calls in the app.post middleware at the server side using promise chaining. The initial problem remains a mystery.

POST requests are sent twice with certain delay between them to Express route

I have an Express route /chat/send for sending messages which gets user's ID from session and message. It works okay, but I noticed that requests are sent again after some period of time, without any action (I was doing something in the background and checked console again). I tried to restart server and check again and problem persists.
This is route:
app.post('/chat/send', ensureAuthenticated, (req, res) => {
let id = req.user.id;
let message = req.body.message;
let currentTime = new Date().getTime();
if (message.trim() !== "") {
console.log('ID: ' + id + ' Message: ' + message + ' Time: ' + currentTime);
}
});
// here is the method for ensuring that authentication is done
let ensureAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) { return next(); }
res.redirect('/');
}
This is client side code:
$("#send-message").on("click", function() {
$.post('/chat/send', { message: $("#chat-message").val() });
$("#chat-message").val("");
});
$("#chat-message").keypress( function(e) {
if (e.which == 13) {
$.post('/chat/send', { message: $("#chat-message").val() });
$("#chat-message").val("");
return false;
}
});
As I said, I was not in the same tab when this happened so I'm pretty sure I haven't clicked on button for sending message or pressed Enter.
Screenshot of terminal:
POSTs can be retried; because you're not replying to the request at all, no response is ever delivered to the browser, and it assumes the request failed. It should then retry the request, which is what appears to be happening here.
To fix, just reply with anything in your Express handler, even if you just call res.end().
Ref: https://www.rfc-editor.org/rfc/rfc2616#section-8.2.4

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.

Node, express, Monk, mongodb: 400 bad request error on post request. Why am I getting this error?

I've been trying to get a simple nodejs API with CRUD functionality working. I'm using express, and 'monk' package for communicating with mongodb. I've successfully pulled data with a GET request.
I'm unable to get a post() function to work. I'm able to insert new documents to mongo when the insert request is called from a GET request that inserts a doc every time it's called. However, no matter what I do, with or without an actual insert request, my post is returning a 400.
Here's my route file:
var express = require('express');
var router = express.Router();
/* GET hours page. (for users to submit hours) */
router.get('/', function (req, res) {
var db = req.db;
var collection = db.get('entries');
collection.find({}, /*{limit:20}, */function (err, docs) {
if (err) {
console.log('couldn\'t load entries');
}
res.json(docs);
});
});
/* POST hours page. (for users to submit hours) */
router.post('/', function (req, res) {
if (!(req.body.job || req.body.code || req.body.hours)) {
handleError(res, 'Invalid user input', 'Must complete input', 400);
}
var db = req.db;
var collection = db.get('entries');
var newEntry = req.body;
collection.insert(newEntry, function (err, docs) {
if (err){
handleError(res, err.message, 'Failed to create new entry');
}
res.json(docs);
});
});
module.exports = router;
I really don't know why ever single post request is returning a 400. I'm thinking it's a problem with my main file, but it has barely been altered from the initial express generated file.
You if condition is wrong. !(req.body.job || req.body.code || req.body.hours) should be !(req.body.job && req.body.code && req.body.hours).
And are you sure you have really post anything? Check the Content-Type of your requests, which should be application/x-www-form-urlencoded;.
I recommand using supertest to test your app. The usage is very simple.
import request = require("supertest");
import should = require("should");
import app = require("../youApp");
describe("POST /foo", () => {
it("should post something", done => {
request(app)
.post("/foo")
.send({job: "my job", code: "...", "hours"})
.expect(200, done);
});
});
Somthing more
replace var with const .
use arrow function instead of function(req, res).

Getting Digits from twilio Gather

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.

Resources