How to Receive WhatsApp Audios Messages Using Twilio for Dialogflow - twilio

I am doing a chatbot with dialogflow-es and I connected it with twilio for whatsapp, but the problem now is that I want that dialogflow receive the audio´s user, but I don´t know how....

In that example, there is a server that receives the incoming webhook request from Twilio. It looks like this:
app.post('/', async function(req, res) {
const body = req.body;
const text = body.Body;
const id = body.From;
const dialogflowResponse = (await sessionClient.detectIntent(
text, id, body)).fulfillmentText;
const twiml = new MessagingResponse();
const message = twiml.message(dialogflowResponse);
res.send(twiml.toString());
});
You can see that the application gets the text from the message from req.body.Body and the user's WhatsApp phone number from req.body.From. When Twilio sends webhooks to this endpoint for messages it sends all the information in the body of the request. You can see all the parameters that Twilio will send in the documentation here.
In this case you are looking for media that comes with the message, so you would first look for the NumMedia parameter. If it is greater than 0 then some media has been sent with the message.
Once you know how many media items have been sent you can then access them in parameters MediaUrl{N} where N is an integer. The media is delivered as a URL, so if you need to access the file you will need to download it.
So, you might deal with this like:
app.post('/', async function(req, res) {
const body = req.body;
const text = body.Body;
const id = body.From;
const numMedia = parseInt(body.NumMedia, 10);
if (numMedia > 0) {
for (let i = 0; i < numMedia; i++) {
console.log(body[`MediaUrl${i}`]);
}
}
const dialogflowResponse = (await sessionClient.detectIntent(
text, id, body)).fulfillmentText;
const twiml = new MessagingResponse();
const message = twiml.message(dialogflowResponse);
res.send(twiml.toString());
});
I'm not sure how you would deal with the audio with respect to Dialogflow, but that's how you access it.

Related

Twilio Whatsapp: Send Location not working

I'm using the FUNCTION Widget in Twilio Studio.
I need to send location inside a message in whatsapp.
I've tried this peice of code inside a function in Twilio:
// This is your new function. To start, set the name and path on the left.
exports.handler = function(context, event, callback) {
// The pre-initialized Twilio Client is available from the `context` object
const twilioClient = context.getTwilioClient();
// Determine message details from the incoming event, with fallback values
const from = event.From || 'whatsapp:+14155238886';
const to = event.To || 'whatsapp:+556181584246';
const body = event.Body || 'Ahoy, World!';
const persistentAction = 'geo:-1.232453, 36.878987';
twilioClient.messages
.create({to, body, from, persistentAction})
.then((result) => {
console.log('Created message using callback');
console.log(result);
console.log(result.sid);
return callback();
})
.catch((error) => {
console.error(error);
return callback(error);
});
};

How to mute a PSTN participant in a Twilio Live room

I have implemented Twilio Voice connect with my Video Room, to let participants join using PSTN dial-in. This works alright, but muting the phone participant is a problem. There seems to be a way to mute the other participants' voice tracks, but that doesn't work for phone participants.
I'm following the implementation in the sample-app, where it sends a 'mute' message on the data track,
const handleMuteSpeaker = () => {
const [localDataTrackPublication] = [...room!.localParticipant.dataTracks.values()];
const messageString = JSON.stringify({ message_type: 'mute', to_participant_identity: speaker });
const messageBuffer = new TextEncoder().encode(messageString).buffer;
localDataTrackPublication.track.send(messageBuffer);
};
which is then handled at the speaker's end, and the track is muted:
const messageString = new TextDecoder().decode(message);
const JSONMessage = JSON.parse(messageString);
if (
JSONMessage.message_type === 'mute' &&
JSONMessage.to_participant_identity === room!.localParticipant.identity
) {
if (isAudioEnabled) {
toggleAudio(); // this disables the audio-track
// other stuff
}
}
What should I do for phone participants ?
Thanks in advance.

Receiving and handling media messages in Twilio-dialogflow WhatsApp integration

I have deployed a server on GCP to receive message traffic from twilio via webhook and integrated it with Google's dialogflow. You can see the original project here "https://github.com/GoogleCloudPlatform/dialogflow-integrations#readme".
The function works fine for receiving and responding via intent detection but it can't handle any media inputs from a user as dialogflow can't interpret it. I've been trying to code a simple IF statement that converts any input media into URL's prior to processing by dialogflow. The full code server.js file is given below:
const express = require('express');
const request = require('request');
const app = express();
const dialogflowSessionClient = require('../botlib/dialogflow_session_client.js');
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const projectId = 'PROJECT-ID';
const phoneNumber = "+1##########";
const accountSid = '*********************';
const authToken = '*******************';
const client = require('twilio')(accountSid, authToken);
const MessagingResponse = require('twilio').twiml.MessagingResponse;
const sessionClient = new dialogflowSessionClient(projectId);
const listener = app.listen(process.env.PORT, function() {
console.log('listner marker');
console.log('Your Twilio01 integration server is listening on port '+ listener.address().port);
});
app.post('/', async function(req, res) {
const body = req.body;
const text = body.Body;
const id = body.From;
console.log('body marker');
const dialogflowResponse = (await sessionClient.detectIntent(text, id, body)).fulfillmentText;
const twiml = new MessagingResponse();
const message = twiml.message(dialogflowResponse);
res.send(twiml.toString());});
process.on('SIGTERM', () => {
listener.close(() => {
console.log('Closing http server.');
process.exit(0);
});
});
I have tried to add my IF statement like below but it fails to execute when placed into the main file.
if (MessagingResponse.NumMedia != "0") {
console.log(MessagingResponse.MediaUrl0);
MessagingResponse = MessagingResponse.MediaUrl0;
console.log(response.toString());
}
you cannot change the const variable value on the next statement so
change your
const text;
to
var text;
and add
if(body.MediaUrl0){
text = body.MediaUrl0;
}
before
const dialogflowResponse = (await sessionClient.detectIntent(
text, id, body)).fulfillmentText;
Twilio developer evangelist here.
You're trying to read the NumMedia and other properties from the MessagingResponse class. You should be trying to read it from the body of the incoming request: req.body.NumMedia.
Edit
Checked your code from the repo. The const still doesn't seem right. Try this:
app.post("/", async function (req, res) {
const body = req.body;
let text;
if (body.NumMedia != "0") {
text = body.MediaUrl0;
} else {
text = body.Body;
}
const id = body.From;
const dialogflowResponse = (await sessionClient.detectIntent(text, id, body))
.fulfillmentText;
const twiml = new MessagingResponse();
twiml.message(dialogflowResponse);
res.send(twiml.toString());
});
In this case we define text with let instead of const and outside of the conditional. That way we can reassign to text and use it later in the function too.

how can i save received image or document file from sender whatsapp using twilio?

I have a scenario like user will send the image or pdf file to twilio whatsapp number so i need to save that image/pdf in folder which will be processed to next level.
How can i save the files? I am using Node SDK.
Thanks in advance.
Assuming you've already configured your webhook on your sandbox page, so that messages containing media from Whatsapp are getting to your app.
As documentation says, you'll receive MediaContentType{N} and MediaUrl{N} as long as body and other parameters. The following snippet was translated-ish from a Python example from official documentation:
const Fs = require('fs')
const Path = require('path')
const Axios = require('axios')
const num_media = req.body.NumMedia;
const media_files = []
for (let i = 0; i <= num_media; i++) {
const id = req.body.MessageSid
const media_url = req.body[`MediaUrl{i}`];
const mime_type = req.body[`MediaContentType{i}`);
media_files.push({'media_url': media_url, 'mime_type': mime_type});
download(media_url, id);
}
async function download(url, name) {
const path = Path.resolve(__dirname, 'files', name)
const writer = Fs.createWriteStream(path)
const response = await Axios({
url,
method: 'GET',
responseType: 'stream'
})
response.data.pipe(writer)
return new Promise((resolve, reject) => {
writer.on('finish', resolve)
writer.on('error', reject)
})
}

How to use a Twilio function to transfer a call to a phone number with an extension?

I'm trying to use a Twilio function to transfer a call to a phone number with an extension.
The Twilio function is called from a Twilio flow.
Right now, the call transfer to the phone number. However, the extension is never invoked.
I added some "w" characters for pause in the "sendDigits"...but it did not change anything.
Here is my Twilio flow
Here is my Twilio function widget with the parameter
Here is the code of the twilio function
exports.handler = function(context, event, callback) {
// set-up the variables that this Function will use to forward a phone call using TwiML
// REQUIRED - you must set this
let phoneNumber = event.PhoneNumber || "NUMBER TO FORWARD TO";
// OPTIONAL
let callerId = event.CallerId || null;
// OPTIONAL
let timeout = event.Timeout || null;
// OPTIONAL
let allowedCallers = event.allowedCallers || [];
// generate the TwiML to tell Twilio how to forward this call
let twiml = new Twilio.twiml.VoiceResponse();
let allowedThrough = true;
if (allowedCallers.length > 0) {
if (allowedCallers.indexOf(event.From) === -1) {
allowedThrough = false;
}
}
let sendDigits = event.sendDigits;
let dialParams = {};
dialParams.sendDigits = sendDigits
if (callerId) {
dialParams.callerId = callerId;
}
if (timeout) {
dialParams.timeout = timeout;
}
if (allowedThrough) {
twiml.dial(dialParams, phoneNumber);
}
else {
twiml.say('Sorry, you are calling from a restricted number. Good bye.');
}
// return the TwiML
callback(null, twiml);
};
Any idea ?
The Dial verb doesn't have a sendDigits attribute, but the REST API does.
You can use the Number noun with the Dial verb, https://www.twilio.com/docs/voice/twiml/number, and its associated URL parameter to reference a TwiML Bin with a Play, https://www.twilio.com/docs/voice/twiml/play, and its digits attribute, to play the DTMF after the dialed party answers the phone, but before the two parties communicate with one another.

Resources