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.
Related
I am simply trying to answer a phone call through the browser using Node.js and Angular.
I can receive phone calls but I am unsure how to answer them. I would like to answer them through the browser. How do redirect them out of "enqueue" and connect them to a live user on the front end? Can anyone help?
Here is where I am at...
FRONT END
receive-call.component.ts
ngOnInit(): void {
// displays all of the data from the incoming caller
this.webSocketService.listen('incoming call').subscribe(res => {
console.log(res)
})
// shows in the front end that there is somebody waiting to talk with a rep
this.webSocketService.listen('enqueue').subscribe(res => {
console.log(res)
this.callSid = this.incomingCall.CallSid
this.callFrom = this.incomingCall.From
console.log(this.incomingCall.From, 'now in enqueue')
})
}
answerCall(){
console.log('answer call button works')
// here is where I want to connect my device and the incoming phone call
}
}
BACK END
server.js
// this is where I point twilio to on an incoming call
app.get('/incoming-call', (req, res) => {
// tell the front end that I have an incoming call
socket.emit('incoming call', req.query)
const twiml = new VoiceResponse();
twiml.say('Thanks for calling.')
// here I redirect the call to go enqueue
twiml.redirect('https://myurl/enque')
res.type('text/xml');
res.send(twiml.toString())
});
app.post('/enque', (req, res) => {
const twiml = new VoiceResponse();
twiml.enqueue({
url: 'Music URL'
}, 'AMG Customer Service')
socket.emit('enqueue')
res.type('text/xml');
res.send(twiml.toString())
});
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) => {
//
});
});
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.
Steps:
Create Azure mobile app with node.js backend. (server)
Create NotificationHub associated to the new mobile app. (server)
Create WinJS App (Universal Windows) in Visual Studio (client)
Associate app with App Store VS > Project > Store > Associate App with Store (client)
Include Mobile Services MobileServices.Web.js to connect with mobile services backend (client)
Connect to mobile service backend (client = new WindowsAzure.MobileServiceClient('https://.azurewebsites.net') (client)
I am having a problem trying to get the tags for push notification hub that is tied to my azure mobile service node.js backend.
I am following this blog post:
https://blogs.msdn.microsoft.com/writingdata_services/2016/04/14/adding-push-notification-tags-from-a-node-js-backend/
on how to create tags on the node.js backend.
When I call the createTags API I am presuming the tag is being created because there is no error being returned.
But when I call getTags API my error routine is firing with the error
An error occurred when retrieving installation
Error: 404 - Installation not found.TrackingId:0615f100-35fe-496e-b63d-53d39d7e1cf9_G1,TimeStamp:10/27/2016 9:46:25 PM
I can't figure out why I am getting this error?
Can anyone see what I am missing or need to do to fix this problem?
Any help would be appreciated.
createTags.js
module.exports = {
"post": function (req, res, next) {
// Get the notification hub used by the mobile app.
var push = req.azureMobile.push;
console.log('create tags installationId ' + req.body.installationId);
console.log('tags ' + req.body.tags.toString());
// Validate for and block any SID tags.
for (var i = 0; i < req.body.tags.length; i++) {
if (req.body.tags[i].search("sid:") !== -1) {
res.status(403)
.send("You cannot set '" + req.body.tags[i] + "' as a tag.");
return;
}
}
// Define an update tags operation.
var updateOperation = [{
"op": "add",
"path": "/tags",
"value": req.body.tags.toString()
}];
// Update the installation to add the new tags.
push.patchInstallation(req.body.installationId, updateOperation, function(error, response){
if(error){
console.log('An error occurred when adding tags\n\n' + error);
res.status(error.statusCode).send(error.detail);
}
else res.status(200).send();
});
}
};
getTags.js
module.exports = {
"post": function (req, res, next) {
// Get the notification hub used by the mobile app.
var push = req.azureMobile.push;
console.log('getting tags');
if (typeof req.body.installationId !== "undefined"){
push.getInstallation(req.body.installationId, function (error, response) {
if (error) {
console.log('An error occurred when retrieving installation\n\n' + error);
res.status(error.statusCode).send(error);
}
else {
console.log("got installation " + req.body.installationId + '\n\n' + JSON.stringify(response));
res.status(200).send(response);
}
});
}
else res.status(200).send();
}
};
main.js - here is my winjs app to create the tag and then check that it was created
client = new WindowsAzure.MobileServiceClient('https://<sitename>.azurewebsites.net');
client.invokeApi("createTags", {
body: {
installationId: client.push.installationId,
tags: ['public']
},
method: "post"
}).then(function (result) {
client.invokeApi("getTags", {
body: {
installationId: client.push.installationId,
},
method: "post"
}).then(function (result) {
WinJS.log(result);
completeDispatcher();
}, function (error) {
WinJS.log(error);
completeDispatcher();
});
}, function (error) {
WinJS.log(error);
completeDispatcher();
});
Update now trying to use this to create a channel first. Then register a listener.
// Request a push notification channel.
Windows.Networking.PushNotifications
.PushNotificationChannelManager
.createPushNotificationChannelForApplicationAsync()
.then(function (newChannel) {
channel = newChannel;
// Register for notifications using the new channel
Machine.Client.push.register('wns', channel.uri, ['public']).done(function (error, response) {
// store the channel
channel.removeEventListener("pushnotificationreceived", pushNotificationReceivedHandler);
channel.addEventListener("pushnotificationreceived", pushNotificationReceivedHandler);
completeDispatcher();
});
}, function (error) {
var dialog = new Windows.UI.Popups.MessageDialog(error, "Error");
dialog.showAsync().then(function () {
completeDispatcher();
});
});
For these type of issues, usually going through Notification Hubs Diagnosis guidelines should give you an idea where the problem is. The 'Verify registrations' section there might be helpful in your case.
If nothing there helps, could update the question with what you've learned?
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.