'context.getTwilioClient(...).document is not a function? - node.js

I'm working with Twilio Functions and I'm trying to use Sync Documents but I keep getting this error: context.getTwilioClient(...).document is not a function
exports.handler = function(context, event, callback) {
context.getTwilioClient().document('data').then(function(doc) {..});
};

Twilio developer evangelist here.
As Andy said, the client you retrieve from context.getTwilioClient() is a generic Twilio REST API client that can access all the resources.
To get your document you need to traverse the objects in the client and get a handle on your service. You need the Sync Service SID, ideally in your environment variables, and the code would look like this:
const client = context.getTwilioClient();
const service = client.sync.services(process.env.SYNC_SERVICE_SID);
service.document('data').fetch().then(function(doc) {
// do something with the document.
});
Let me know if that helps at all.

Related

how does users.watch (in gmail google api) listen for notifications?

I am confused as to how should the watch feature in the gmail API be implemented to recieve the push notificatons inside a node.js script. Should I call the method inside an infinite loop or something so that it doesn't stop listening for notifications for email once after the call is made?
Here's the sample code that I've written in node.js:
const getEmailNotification = () => {
return new Promise(async (resolve, reject) => {
try{
let auth = await authenticate();
const gmail = google.gmail({version: 'v1', auth});
await gmail.users.stop({
userId: '<email id>'
});
let watchResponse = await gmail.users.watch({
userId: '<email id>',
labelIds: ['INBOX'],
topicName: 'projects/<projectName>/topics/<topicName>'
})
return resolve(watchResponse);
} catch(err){
return reject(`Some error occurred`);
}
})
Thank you!
Summary
To receive push notifications through PUB/SUB you need to create a web-hook to receive them. What does this mean? You need a WEB application or any kind of service that exposes a URL where notifications can be received.
As stated in the Push subscription documentation:
The Pub/Sub server sends each message as an HTTPS request to the subscriber application at a pre-configured endpoint.
The endpoint acknowledges the message by returning an HTTP success status code. A non-success response indicates that the message should be resent.
Setup a channel for watch the notifications could be summarized in the following steps (the documentation you refer to indicates them):
Select/Create a project within the Google Cloud Console.
Create a new PUB/SUB topic
Create a subscription (PUSH) for that topic.
Add the necessary permissions, in this case add gmail-api-push#system.gserviceaccount.com as Pub/Sub Publisher.
Indicate what types of mail you want it to listen for via Users.watch() method (which is what you are doing in your script).
Example
I give you an example using Apps Script (it is an easy way to visualize it, but this could be achieved from any kind of WEB application, as you are using Node.js I suppose that you are familiarized with Express.js or related frameworks).
First I created a new Google Apps Script project, this will be my web-hook. Basically I want it to make a log of all HTTP/POST requests inside a Google Doc that I have previously created. For it I use the doPost() equal to app.post() in Express. If you want to know more about how Apps Script works, you can visit this link), but this is not the main topic.
Code.gs
const doPost = (e) => {
const doc = DocumentApp.openById(<DOC_ID>)
doc.getBody().appendParagraph(JSON.stringify(e, null, 2))
}
Later I made a new implementation as a Web App where I say that it is accessible by anyone, I write down the URL for later. This will be similar to deploying your Node.js application to the internet.
I select a project in the Cloud Console, as indicated in the Prerequisites of Cloud Pub/Sub.
Inside this project, I create a new topic that I call GmailAPIPush. After, click in Add Main (in the right bar of the Topics section ) and add gmail-api-push#system.gserviceaccount.com with the Pub/Sub Publisher role. This is a requirement that grants Gmail privileges to publish notification.
In the same project, I create a Subscription. I tell it to be of the Push type and add the URL of the Web App that I have previously created.
This is the most critical part and makes the difference of how you want your application to work. If you want to know which type of subscription best suits your needs (PUSH or PULL), you have a detailed documentation that will help you choose between these two types.
Finally we are left with the simplest part, configuring the Gmail account to send updates on the mailbox. I am going to do this from Apps Script, but it is exactly the same as with Node.
const watchUserGmail = () => {
const request = {
'labelIds': ['INBOX'],
'topicName': 'projects/my_project_name/topics/GmailAPIPush'
}
Gmail.Users.watch(request, 'me')
}
Once the function is executed, I send a test message, and voila, the notification appears in my document.
Returning to the case that you expose, I am going to try to explain it with a metaphor. Imagine you have a mailbox, and you are waiting for a very important letter. As you are nervous, you go every 5 minutes to check if the letter has arrived (similar to what you propose with setInterval), that makes that most of the times that you go to check your mailbox, there is nothing new. However, you train your dog to bark (push notification) every time the mailman comes, so you only go to check your mailbox when you know you have new letters.

Twiml Connect method issue

So i'm trying to make it so an outbound call gets redirected to my Autopilot system, but my Twiml does seem to recognize the connect function built into the voice response method
I've tried to have the account sid be provided, call, and even load the link in a browser, it just gives the same error
Heres the code im using
exports.handler = function(context, event, callback) {
let res = new Twilio.twiml.VoiceResponse();
console.log(res.toString());
res.connect().autopilot(context.AI_SID);
console.log(res.toString());
callback(null, res);
};
It should return the code below, but seems like this doc is not accurate: https://www.twilio.com/docs/voice/twiml/connect
<Response>
<Connect>
<Autopilot>#####</Autopilot>
</Connect>
</Response>
Update the Twilio helper libraries under your Twilio Functions, Configure, to use a release that added this verb.
https://github.com/twilio/twilio-node/blob/master/CHANGES.md

How to run Alexa skill with the alexa-sdk on own server with Node.js without Lambda drop-in?

The Alexa skill docs will eventually allow you to send webhooks to https endpoints. However the SDK only documents lambda style alexa-sdk usage. How would one go about running Alexa applications on one's own server without anything abstracting Lambda? Is it possible to wrap the event and context objects?
You can already use your own endpoint. When you create a new skill, in the configuration tab, just choose HTTPS and provide your https endpoint. ASK will call your endpoint where you can run anything you want (tip, check ngrok.com to tunnel to your own dev machine). Regarding the event and context objects; your endpoint will receive the event object information. You don't need the context object for anything, that just lets you interact with Lambda-specific stuff (http://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html). Just make sure that you comply with the (undocumented) timeouts by ASK and you are good to go.
Here's a way to do this that requires only a small change to your Skill code:
In your main index.js entry point, instead of:
exports.handler = function (event, context) {
use something like:
exports.myAppName = function (funcEvent, res) {
Below that, add the following workaround:
var event = funcEvent.body
// since not using Lambda, create dummy context with fail and succeed functions
const context = {
fail: () => {
res.sendStatus(500);
},
succeed: data => {
res.send(data);
}
};
Install and use Google Cloud Functions Local Emulator on your laptop. When you start and deploy your function to the emulator, you will get back a Resource URL something like http://localhost:8010/my-project-id/us-central1/myAppName.
Create a tunnel with ngrok. Then take the ngrok endpoint and put it in place of localhost:8010 in the Resource URL above. Your resulting fulfillment URL will be something like: https://b0xyz04e.ngrok.io/my-project-id/us-central1/myAppName
Use the fulfillment URL (like above) under Configuration in the Alexa dev console, selecting https as the Service Endpoint Type.

Trouble with Twilio / TwiML statusCallback using Node.js

When a user texts my number, I would like to respond with a message using TwiML. I'd also like to know whether my response message sends or fails. I'm creating my TwiML response using the Twilio library for Node.js.
Here is my code:
const response = new twilio.TwimlResponse();
response.message(Response, {
statusCallback: '/sms/status/'
});
Here is the code for the route. Please note that the router is mounted upon the "/sms/" router:
router.post('/status/', acceptRequestsOnlyFromTwilio, (req, res) => {
const Event = require('./../models/schemas/event');
const event = new Event({
description:
`MessageSid = ${req.body.MessageSid}
MessageStatus = ${req.body.MessageStatus}`
});
event.save();
console.log(
`MessageSid = ${req.body.MessageSid}
MessageStatus = ${req.body.MessageStatus}`
);
res.sendStatus(200);
});
When I check my logs using the Heroku CLI, I don't log nor do I see a record when I check MongoDB.
Anyone have any ideas or tips on how I can go about debugging this or if I'm implementing this incorrectly?
Thanks for you time!
Twilio developer evangelist here.
Firstly, have you set your Messaging request URL for the Twilio phone number you are using? Is it pointing at the correct route for your Message TwiML response?
Also, your first code block should also be within a router.post endpoint for your server. Do you correctly return the TwiML response as the server response?
As a tip, it might be better to develop this application locally and test your webhook endpoints using a tool like ngrok. I love using ngrok to test webhooks.

how to connect two anonymous callers together using twilio

I am currently doing using node js twilio module for a functionality in a project that i am working on for a client. Basically the server is going to initiate a call using twilio api to call a certain person A the connect him to another person B. I am new to twilio so i am still a noob, but this is the code i have written so far. Please i need u guys input on how to achieve this. cheers
var client = require('twilio')(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN);
exports.makeCall = function(callDetails, cb) {
client.makeCall({
to:'+16515556677', // Any number Twilio can call
from: TWILIO_CALLER_ID,
url: 'https://demo.twilio.com/welcome/voice' // A URL that produces an XML document (TwiML) which contains instructions for the call
}, function(err, responseData) {
//executed when the call has been initiated.
console.log(responseData.from); // outputs "+14506667788"
var resp = new client.TwimlResponse();
resp.say('Welcome to Acme Customer Service!')
.gather({
action:'http://www.example.com/callFinished.php',
finishOnKey:'*'
}, function() {
this.say('Press 1 for customer service')
.say('Press 2 for British customer service', { language:'en-gb' });
});
});
};
Twilio developer evangelist here.
You're part way there with this, but you don't want to be creating a TwiML response in the callback to your call to client.makeCall. The responseData there is a representation of the call in Twilio's system.
What you need to do is provide a URL to the makeCall function that hosts some TwiML that connects the call to another phone number. Currently you have the demo URL in place, so you'll need to point that to a URL that you own.
There's a very good in depth tutorial on how to accomplish all of this on the Twilio site which you might find helps out. You can find the tutorial here, give it a go and let me know if that helps.

Resources