I'm trying to get status callbacks for various room events, but twilio is not sending any events to my callback URL, I've used the following code to create a room using the documentation i found here
app.get('/createRoom', function (req, res) {
var client = new Twilio(twilioApiKey, twilioApiSecret, {
accountSid: twilioAccountSid
});
client.video.rooms.create({
uniqueName: myRoomName,
statusCallback: 'myCallbackURL'
}).then((room) => {
//
});
});
Related
I am trying to use callback function on the server when I emit to a room. In the room there is only 1 device that has a specific channel number. I can emit to it but can not get the callback to work.
server
socket.to(userId).emit('request-api', options, (response: any) => {
console.log(response);
});
client
socket.on('request-api', (arg1, callback) => {
console.log(arg1);
callback({
status: 'ok',
});
});
Is there a way that I can have the server to emit event and get callback. Nodejs project
I want to fordward a call to a Studio Flow after the agent in flex hangs up so a CSAT survey can play for the user.
I created a plugin that calls a function inside Twilio but there is a "Error - 11200" after the forwarding is done.
I replaced the hang up action so it redirects the call to a function in twilio. The function is supossed to send the call to a flow that will play the survey. I suspect the problem has to do with authentication but I can't find much about it.
I'm fairly new to twilio, so any help will be greatly appreciated
This is the part of the plugin that calls the function:
flex.Actions.replaceAction("HangupCall", (payload) => {
console.log('task attributes: ' + JSON.stringify(payload.task.attributes));
if (payload.task.attributes.direction === "inbound") {
// Describe the body of your request
const body = {
callSid: payload.task.attributes.call_sid,
callerId: payload.task.attributes.from,
destination: '+18xxxxxxxx',
Token: manager.store.getState().flex.session.ssoTokenPayload.token
};
// Set up the HTTP options for your request
const options = {
method: 'POST',
body: new URLSearchParams(body),
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
};
// Make the network request using the Fetch API
fetch('https://TWILIO INSTANCE.twil.io/TransferUtil', options)
.then(resp => resp.json())
.then(data => console.log(data));
} else {
original(payload);
}
});
And this is the function in twilio:
const TokenValidator = require('twilio-flex-token-validator').functionValidator;
exports.handler = TokenValidator(async function(context, event, callback) {
const response = new Twilio.Response();
response.appendHeader('Access-Control-Allow-Origin', '*');
response.appendHeader('Access-Control-Allow-Methods', 'OPTIONS, POST, GET');
response.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
response.appendHeader('Content-Type', 'application/json');
const client = require('twilio')();
const callSid = event.callSid;
const callerId = event.callerId;
const destination = event.destination;
console.log('Call Sid:', callSid);
console.log('Transfer call from:', callerId, 'to:', destination);
try {
let url = 'https://studio.twilio.com/v2/Flows/FWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Executions';
let call = await client.calls(callSid).update({method: 'POST', url: encodeURI(url)});
console.log(JSON.stringify(call));
response.appendHeader('Content-Type', 'application/json');
response.setBody(call);
callback(null, response);
}
catch (err) {
response.appendHeader('Content-Type', 'plain/text');
response.setBody(err.message);
console.log(err.message);
response.setStatusCode(500);
callback(null, response);
}
});
EDIT:
In the error Log I get this information:
Argh, I read the error wrong. There isn't anything wrong with the Function, the error is coming from the call trying to make a webhook request to the URL https://studio.twilio.com/v2/Flows/FWXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Executions. That's the REST API trigger and needs to be requested in the same way as any other API request using your account credentials or API keys.
You should set that URL to the webhook trigger URL, which looks like https://webhooks.twilio.com/v1/Accounts/${ACCOUNT_SID}/Flows/${FLOW_SID}. Then the call will be able to request it as part of a normal webhook flow.
I am trying to get back StatusCallback events when I dial from my browser to phone call.
When user clicks on dial in browser I am sending the following response to twilio:
const dial = twiml.dial({
callerId: Meteor.settings.private.twilio.TWILIO_CALLER_ID,
answerOnBridge: true,
record: "record-from-answer-dual",
StatusCallbackEvent: ["initiated", "ringing", "answered", "completed"],
StatusCallback,
recordingStatusCallback: recordURLCallback,
});
dial.number(toNumber);
I have registered webhook both in twilio console and also sending via command but i'm not receiving 'ringing', 'answered' events from twilio
WebApp.connectHandlers.use("/twilio-status-callback", function( req, res, next ) {
console.log('***status url callback***');
var body = "";
req.on('data', Meteor.bindEnvironment(function (data) {
body += data;
}));
req.on('end', Meteor.bindEnvironment(function () {
body = qs.parse(body)
console.log(body);
res.end();
}));
});
I am only receiving completed event, how to get other statuses to so that I can show ringing UI when it is ringing and hangup button when answered?
Twilio developer evangelist here.
In your example code you don't include an option for StatusCallback so there is no webhook for Twilio to call, only a recordingStatusCallback. Also, the Node library actually translates the keys from lower-camel-case, so the keys should be statusCallback. Try updating the code to something like this and let me know how it goes:
const dial = twiml.dial({
callerId: Meteor.settings.private.twilio.TWILIO_CALLER_ID,
answerOnBridge: true,
record: "record-from-answer-dual",
statusCallbackEvent: ["initiated", "ringing", "answered", "completed"],
statusCallback: statusURLCallback,
recordingStatusCallback: recordURLCallback,
});
dial.number(toNumber);
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.
I'm trying to create a basic app in node.js that a) tracks a keyword in twitter and temporarily stores messages relating to that keyword, b) after enough messages have been accumulated, return it to the user. I'm using the ntwitter library.
I've a basic long polling system implemented on my client and server side, but I'm having some trouble on verification. The way I set it up currently, it verifies the user each time /api/streamfeed is called, so potentially every 30sec (since I have a 30s timeout schedule) before checking the stream. I'm thinking this will get me into trouble since I believe verification is rate-limited? Is there a way to check whether I'm verified without having to ping Twitter's API (perhaps store a boolean after the first attempt)?
Client side:
//upon receiving a response, poll again
function getStreamFeed() {
console.log('calling getStreamFeed');
$http.get('/api/streamfeed').success(function(data) {
console.log(data)
getStreamFeed();
});
};
setTimeout(getStreamFeed, 1000);
Server side:
app.get('/api/streamfeed', function(req, res) {
/*
...
polling code
...
*/
twit.verifyCredentials(function(err, data) {
if (err) res.send(404);
twit.stream('statuses/filter', {
track: 'justin bieber'
}, function(stream) {
stream.on('data', function(data) {
console.log(data.text)
messages.push(data.text);
});
})
});
});
I'd send the credentials back and resend them again... this could be a bool, or actual credentials to use. these aren't your private keys or anything, only the user's.
could also be sent in headers and cookies and properly hashed etc.
this just simply shows a pattern that should work.
client side:
function getStreamFeed(credentials) {
//upon receiving a response, poll again
console.log('calling getStreamFeed');
var url = '/api/streamfeed';
if (credentials) {
url += '&credentials=' + credentials;
}
$http
.get(url)
.success(function(data) {
console.log(data)
getStreamFeed(true);
});
};
setTimeout(getStreamFeed, 1000);
Server side:
app.get('/api/streamfeed', function(req, res) {
function twitStream () {
twit.stream('statuses/filter', {track: 'justin bieber'}, function(stream) {
stream.on('data', function(data) {
console.log(data.text)
messages.push(data.text);
});
}
}
var credentials = req.query.credentials;
if (credentials) {
twitStream()
}
twit.verifyCredentials(function(err, data) {
if (err) res.send(404);
twitStream()
});
});