Here's my code
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.VoiceResponse();
let gather = twiml.gather({
input: 'dtmf',
finishOnKey: '#'
});
gather.play("Please enter your user ID");
callback(null, twiml);
var got = require('got');
var requestPayload = event;
got.post('http://www.test.com/test.php?test=' + JSON.stringify(requestPayload), {
body: JSON.stringify(requestPayload),
headers: {
'accept': 'application/json'
},
json: true
})
.then(function(response) {
console.log(response.body)
callback(null, response.body);
})
.catch(function(error) {
callback(error)
})
};
I got successful response from url , but i need to ask second question . How to continue from here.
Thanks
Twilio developer evangelist here.
If you want to use just the one function for this, then you need it to do different things depending on whether the user has just called or if they have entered some digits.
I've rearranged your code a bit and left comments to guide you:
const got = require('got');
exports.handler = function(context, event, callback) {
// We can set up our initial TwiML here
let twiml = new Twilio.twiml.VoiceResponse();
let gather = twiml.gather({
input: 'dtmf',
finishOnKey: '#'
});
if(event.Digits) {
// The user has entered some digits to answer the question so we post to
// your API and only callback when we get the results
got.post('http://www.test.com/test.php', {
body: JSON.stringify(event),
headers: {
'accept': 'application/json'
},
json: true
})
.then(function(response) {
// Check the response and ask your second question here
gather.say("Please enter your case ID.");
callback(null, twiml);
})
.catch(function(error) {
// Boo, there was an error.
callback(error)
});
} else {
// The user hasn't entered anything yet, so we ask for user ID
gather.say("Please enter your user ID");
callback(null, twiml);
}
};
Let me know how that works for you. You might find that if you then need to do even more work that a single Function is not the best idea here and you should direct the user to a new Function to continue the call after the case ID is entered.
Let me know if this helps at all.
Related
I want to send parallel POST requests in puppeteer. I have to change the payload with every request (URL remains the same).
I tried using puppeteer cluster, but how do I change payload with every request when I queue the same request?
Using normal puppeteer
(async() => {
const browser = await puppeteer.launch({
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-web-security",
],
executablePath: 'C:/Program Files/..',
headless: false,
});
for(const id of Ids) {
const page = await browser.newPage();
await page.setDefaultNavigationTimeout(60000);
await page.evaluateOnNewDocument(() => {
// Some code
})
await page.setRequestInterception(true);
// Request intercept handler... will be triggered with
// each page.goto() statement
page.on('request', interceptedRequest => {
// Here, is where you change the request method and
// add your post data
var data = {
'method': 'POST',
'postData': JSON.stringify({
....
"similarMaterialId": `${id}`,
}),
'headers': {
.....
},
};
// Request modified... finish sending!
interceptedRequest.continue(data);
});
const response = await page.goto('https://.../getProductInfo');
const responseBody = await response.json();
try {
let title = responseBody.description;
let price = responseBody.price;
fs.appendFile('temp.tsv', `${title}\t${price}\n`, function (err) {
if (err) throw err;
})
}
catch {
console.log(id)
}
await page.close();
}
console.log("Code ended!!")
await browser.close();
})();
I want to create many pages in parallel on a single browser.
Is it possible to test graphql subscriptions using k6 framework?
I tried to do it, but did not have much success. Also tried to do it with k6 websockets, but did not help.
Thanks
Grapqhql Subscription is based on Websockets so this is theoretically possible to implement using k6 WebSocket.
You can also refer to the documentation for subscriptions here.
You can also use the playground and Networks tab in developer tools to figure out the messages/requests that are sent to the server.
Here is how I was able to achieve it:
import ws from "k6/ws";
export default function(){
const url = "ws://localhost:4000/graphql" // replace with your url
const token = null; // replace with your auth token
const operation = `
subscription PostFeed {
postCreated {
author
comment
}
}` // replace with your subscription
const headers = {
"Sec-WebSocket-Protocol": "graphql-ws",
};
if (token != null) Object.assign(headers,{ Authorization: `Bearer ${token}`});
ws.connect(
url,
{
headers,
},
(socket) => {
socket.on("message", (msg) => {
const message = JSON.parse(msg);
if (message.type == "connection_ack")
console.log("Connection Established with WebSocket");
if (message.type == "data") console.log(`Message Received: ${message}`)
});
socket.on("open", () => {
socket.send(
JSON.stringify({
type: "connection_init",
payload: headers,
})
);
socket.send(
JSON.stringify({
type: "start",
payload: {
query: operation,
},
})
);
});
}
);
}
Hope this helps! 🍻
I am using Twilio Studio for to collect messages for our small church. When someone records a voicemail, I am using a function to send the recording URL to the group members. Here is what that function looks like currently:
var groupmembers = [
{
name: 'Person1',
number: '+11111111111'
},
{
name: 'Person2',
number: '+11111111111'
}
];
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.MessagingResponse();
groupmembers.forEach(function(member) {
// Now, forward on the message to the group member, using the sender's name
twiml.message(`Text from ${event.senderFrom}: ${event.senderMessage}`, {
to: member.number
});
})
callback(null, twiml);
};
This gives me a '12200 Schema validation warning' with the detail: Invalid content was found starting with element 'Message'. One of '{Play
I'm fairly sure the issue is because I am trying to send an SMS during a call but I am not sure how to update my TWIML or Studio flow to accommodate for this.
Any help is appreciated!
you need the REST API rather then TwiML in this case. You could use code similar to what is shown below to do this.
Make sure to check the box below, under Function Config for your Function,
exports.handler = function(context, event, callback) {
const twilioClient = context.getTwilioClient();
let groupMembers = [
{
name: 'Person1',
number: '+14701111111'
},
{
name: 'Person2',
number: '+18082222222'
},
{
name: 'Person3',
number: '+18021111111'
}
];
function sendSMS(member) {
return twilioClient.messages.create({
from: '+13054444444',
to: member.number,
body: 'Hello World!'
});
}
let promises = [];
groupMembers.forEach((member) => {
console.log(member);
promises.push(sendSMS(member));
});
Promise.all(promises)
.then((values) => {
console.log(values);
callback(null,"Success");
})
.catch(error => {
console.log(error);
callback("Failure");
});
};
Is there a way to send email from Twilio function? I understand that we can use sendgrid. I am looking a simpler solution.
Twilio evangelist here. 👋
As of now, you can use SendGrid from within a Twilio Function. The code below does the job for me and I just sent an email via a function
exports.handler = function(context, event, callback) {
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: 'sjudis#twilio.com',
from: 'test#example.com',
subject: 'Sending with SendGrid is Fun',
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>',
};
sgMail.send(msg)
.then(() => {
callback(null, 'Email sent...');
})
.catch((e) => {
console.log(e);
})
};
The above email will most like end up in spam as test#example.com is not a very trust worthy email address. If you want to send emails from your own domains additional configuration is needed.
To run the code inside of the function, you have to make sure to install the sendgrid/mail mail dependency and provide the sendgrid token in the function configuration.
If you want to use this function to power e.g. messages you have to make sure that your return valid TwiML. :) When you create a new function you will get examples showing on how to do that.
Hope that helps. :)
Another way is to use the SendGrid API
const got = require('got');
exports.handler = function(context, event, callback) {
const requestBody = {
personalizations: [{ to: [{ email: context.TO_EMAIL_ADDRESS }] }],
from: { email: context.FROM_EMAIL_ADDRESS },
subject: `New SMS message from: ${event.From}`,
content: [
{
type: 'text/plain',
value: event.Body
}
]
};
got.post('https://api.sendgrid.com/v3/mail/send', {
headers: {
Authorization: `Bearer ${context.SENDGRID_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
})
.then(response => {
let twiml = new Twilio.twiml.MessagingResponse();
callback(null, twiml);
})
.catch(err => {
callback(err);
});
};
};
Source: https://www.twilio.com/blog/2017/07/forward-incoming-sms-messages-to-email-with-node-js-sendgrid-and-twilio-functions.html
I'm using Collect in the first Autopilot task to get the date from the user (i.e. Jan 31, 2019). Then I am trying to use that variable (date) to search an Airtable database for that specific row. I want to return the results of that row to the user ("on Jan 31 the Main Theater is playing this movie, the Other Theater is playing...).
My Airtable Get code is below, but I am unsure how to assign the returned data to variables that I can read back to the user.
exports.handler = function(context, event, callback) {
var Airtable = require('airtable');
var base = new Airtable({apiKey:
'apikey'}).base('basekey');
base('Blockouts').find('recbGHAQopLQdCOHK', function(err, record) {
if (err) { console.error(err); return; }
console.log(record);
});
}
and here's the output that Airtable will send back:
{
"id": "recbGHAQopLQdCOHK",
"fields": {
"Date": "2019-02-02",
"Main Theater": "Star Wars",
"Other Theater": "Avengers"
},
"createdTime": "2019-02-02T21:21:48.000Z"
}
Twilio evangelist here.
If your Airtable Get code is not there already, it should go in a Twilio function (which supports Node.js)! that is pointed at an Autopilot task whose actions code has something like this:
{
"actions": [
{
"redirect": {
"uri": "https://your-twilio-function-path.twil.io/airtable-or-whatever-if-this-is-your-path"
}
}
]
}
Then in your Twilio function/Airtable Get code, you should modify your Twilio Response object to accept all requesting origins and have that look something like this:
exports.handler = function(context, event, callback) {
let response = new Twilio.Response();
let headers = {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json"
};
var responseObject = {"actions":[
{ "say": "Try again" }
]};
response.setHeaders(headers);
var Airtable = require('airtable');
var base = new Airtable({apiKey: 'apikey'}).base('basekey');
base('Blockouts').find('recbGHAQopLQdCOHK', function(err, record) {
if (err) { console.error(err); return; }
console.log(record);
}).then(res => {
var date = res.data[0].fields.date;
responseObject = {"actions":[
{ "say": date }
]};
callback(null, responseObject);
});
};
I have not tested this code with your Airtable output (famous last words of a programmer), but used almost exactly the same code when making an Axios request to an API where I saved some of the data returned from that call in a variable, so it should be similar.
Hope this helps.