Answer call on browser with Twilio and Angular - node.js

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())
});

Related

NodeJS Express Routing - Only first request gets rendered

In the server script I try to deliver different html files. When app.post('/login'...) comes in, res.sendFile() is working and the html gets rendered. On the second call, whenn app.get('/go') comes in, the file gets served, but not displayed. I cannot explain why the second HTML file is not displayed. What am I doing wrong?
the second request comes from a fetch request in a javascript
socket.on('gameStarted', (data) => {
console.log("Game started");
fetch('/go', {method: 'GET'});
})
served but not displayed
app.post('/login', async (req, res, next) => {
var roomNR = req.body.player.gameCode;
var playerName = req.body.player.nickname;
var codeValid = await checkCode(activeRoomsCollection, gameCodes, roomNR);
var playerExists = await playerCollection.findOne({ playerName: playerName })
if (codeValid) {
if ((playerExists === null) || !playerExists) {
playerCollection.insertOne({ room: roomNR, playerName: playerName, state: false });
console.log(`Added player '${playerName}' with roomnumber '${roomNR}'`);
res.sendFile(path.join(__dirname + '/../../public/lobby.html'), function (err) {
if (err) {
console.log(err);
res.status(err.status).end();
}
else {
console.log('Sent Lobby');
}
});
} else {
// updateDomElement(player, elementId, data)
//res.send('Benutzername existiert bereits');
}
} else {
res.send('Code ungültig');
}
});
app.get('/go', (req, res, next ) => {
res.sendFile(path.join(__dirname + '/../../public/raetsel1.html'), function (err) {
if (err) {
console.log(err);
res.status(err.status).end();
}
else {
console.log('Sent Raetsel1');
}
});
});
fetch() never displays anything on its own. It's a way for your Javsascript to issue http requests to remote servers and those servers then return content back to your Javascript. The result from those http requests ONLY goes to your Javascript. Nothing in the view of the page is affected at all by a fetch() call.
If you want the result of a fetch() call to display something in your page, you would need to write Javascript to do that (to insert content into the current page).
If, instead, you just want the browser to go to a new page, then change from this:
fetch('/go', {method: 'GET'});
to this:
window.location = "/go";
This will cause the browser to go to the URL, retrieve the content and display it. This will shut-down the current page and load and display a new page and the URL in the URL-bar in the browser will show the updated location.
Note that if you have socket.io code in both pages, it will disconnect the current socket.io connection and then run the Javascript in the new page - causing it to create a new socket.io connection (if you have code in the new page to do that) as that is what happens to socket.io connections when you load and display a new web page in the browser.

How do you programmatically exit a node.js/express route on an event?

I want to be able to exit execution of a post route when an event is sent from the client-side. I'm using socket.io but I'm not sure it can do what I want. I am using the uploads route to process a file, but if the user deletes the file, I want the app.post execution to end, similar to either a res.end() or return statement.
My app in the front-end receives a file from the user and immediately is sent to the post route for processing. If the user deletes the file and uploads a new one, the previous post route is still going. I want to make sure the previous one was terminated, cancelled, etc.
I'm currently using socket.io to communicate front-end to back-end.
How can I achieve this?
app.post('/uploads', async (req, res) => {
// async func1
// async func2
// if we receive an event from the front end while processing here, how can I exit the post route?
// async func3
});
You can add UUID for each request you make and return it to the front-end. The request will be resolved with the 202 ACCEPTED status code meaning the request was accepted and being handled but the HTTP request will be resolved.
Now you can implement a resourceManagerServeic that will allow APIs (http or ws) to change the state of a resource (like canceling it).
app.post('/uploads', async (req, res) => {
const resourceUuid = resourceManagerServeic.createResource();
res.status(202); // ACCEPTED
res.send({ uuid: resourceUuid });
// start besnise logic
await function1();
if(resourceManagerServeic.isCanceled(resourceUuid)) {
// cleanup
return; // stop request handling
}
await function2();
if(resourceManagerServeic.isCanceled(resourceUuid)) {
// cleanup
return; // stop request handling
}
await function3();
if(resourceManagerServeic.isCanceled(resourceUuid)) {
// cleanup
return; // stop request handling
}
});
app.del('/uploads/:resourceUuid', async (req, res) => {
resourceManagerServeic.cancle(req.params.resourceUuid);
res.end() // handle response
});
I guess that your are using Express. Take a look at express-async-handler
You can invoke it
const asyncHandler = require('express-async-handler')
app.post('/upload', asyncHandler(async(req, res) => {
await firstfunc()
await secondfunc()
}))

Twilio conference connection delay

I'm using Twilio to set up an inbound call center. I'm using SIP softphones as my endpoints. I have virtually everything working the way I want it, but there is major issue when trying to start a "Conference" to one of my sip endpoints.
The service rep does not hear the callers words until about 7 seconds into the call. The inbound caller can hear the service rep just fine. This is only a problem with the "Conference." The code below also illustrates a direct connection via dialing an extension where the connection delay does not occur at all.
// Inbound Call to Twilio Number
routes.post('/twilio/phone/inbound', (req, res) => {
const twilioVoice = new VoiceResponse();
const gather = twilioVoice.gather({
action: '/twilio/phone/enqueue',
numDigits: 3,
timeout: 2
});
gather.say('For general inquiries, press 1. If you know the extension of the person you are trying to reach, please enter it now.', {
loop: 5
});
twilioVoice.say('Sorry, I did not get a response. Good bye.');
twilioVoice.hangup();
res.type('text/xml');
res.send(twilioVoice.toString());
});
// Second endpoint to process response from above
routes.post('/twilio/phone/enqueue', (req, res) => {
var pressedKeys = req.body.Digits;
var twilioVoice = new VoiceResponse();
if (pressedKeys.length === 3) {
console.log("Direct call via extension.")
twilioVoice.say(`Please hold while we attempt to connect you to extension`);
twilioVoice.dial().sip('sip:employee#businessname.sip.us1.twilio.com');
// Once connected, both parties can hear each other immediately.
res.send(twilioVoice.toString());
} else {
twilioVoice.enqueue({
workflowSid: process.env.WORKFLOW_SID,
});
res.type('text/xml');
res.send(twilioVoice.toString());
}
});
// Workflow AssignmentCallbackUrl
routes.post('/twilio/phone/assignworker', (req, res) => {
res.type('application/json');
// The service rep does not hear the callers words until about 7 seconds into the call
res.send({
instruction: "conference",
to: "sip:employee#businessname.sip.us1.twilio.com"
});
});

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 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.

Resources