aws lex v2 dynamic fulfillment from backend - node.js

Context
I'm using aws lex V2 and I have already set up a flow so that the user can make an appointment. The thing is that I would like to return (dynamic values) to the user something like:
Expected result
use dynamic values from the backend
ex:
Your appointment has been confirmed. Please keep the following code: {{appointment_code}} when you show up to the interview.
Actual Result
ex:
Your appointment has been confirmed.
When you set up the fulfillment output in aws lex v2, you defined the "static" content of the response, or add the value of the slots using {slotName} in the sentence. No matter what a set my message content from my backend response. i always get the response configure from the aws lex console, but not from the backend.
some code
The response that I'm using after i get all the necessary slots and generate the appointment "code reference" is the following:
function close(sessionAttributes, message) {
return {
"sessionState":{
sessionAttributes,
"dialogAction": {
"type": 'Close',
},
"intent": {
"name": "PetitionsIntent",
"state": "Fulfilled"
},
"messages": [
{
"contentType": "PlainText",
"content": `cool, the apointment code is ${ap_code}`,
}
],
}
};
}
The code works and the intent is fulfilled, but I get the response from the pre-defined lex console(image above) and not from the backend response.
Is there a way to overwrite the predefined output and use the lambda response instead?
What am I missing?

It would appear that your Lambda function has not been invoked.
Clicking the Advanced options button under your fulfillment message will slide in a menu from the right.
Ensure that you've checked the Use a Lambda function for fulfillment option under the Fulfillment Lambda code hook heading.
This assumes that you have correctly configured your bot to make use of a Lambda function.
Also note that Lex will use a different value for invocationSource to denote that all slots have been fulfilled. So your Lambda function will need to look out for FulfillmentCodeHook instead of DialogCodeHook.

Related

How can I get the phone number from Twilio in fulfillment dialogflow

I'm working in a whastapp bot between Twilio and Dialogflow. In one of the intents, I'm sending media files from dialogflow to the user. Here it's the problem, now it's working with my mobile number hardcoded, but I need to access to the user phone number in each case to send the media file.
I develop this in fulfillment dialogflow, inline editor, using some nodejs code, but there I can't access to the user number.
Fulfillment node js
function sendAudioMensaje(agent) {
client.messages.create({
body: 'Body message',
to: 'whatsapp:+34---------', // Text to this number
from: 'whatsapp:+14155238886', // From a valid Twilio number
mediaUrl: 'https://demo.twilio.com/owl.png'
}).then((message) => agent.add(message.sid));
}
I expect that the message would be sent to the current number in each conversation
Twilio developer evangelist here.
As far as I can tell, the Dialogflow webhook request comes with a originalDetectIntentRequest property in the JSON. This contains a OriginalDetectIntentRequest object, which has a payload property that contains the original request.
I'd start by logging the contents of the webhook request to see what is fully available to you though.
Let me know if that helps at all.
In the payload of the OriginalDetectIntent request you will see a JSON like this in the webhook if it's enabled.
{
"source": "twilio",
"data": {
"SmsSid": "",
"Body": "",
"SmsStatus": "received",
"MessageSid": "",
"ApiVersion": "2010-04-01",
"From": "",
"AccountSid": "",
"NumMedia": "0",
"To": "",
"SmsMessageSid": "",
"NumSegments": "1"
}
}

Can a webhook server have no response?

I have a dialogflow implementation using Google assistant, a nodeJS server to serve the webhook calls. Some of the user intents are empty phrases, and they do not need any response from webhook server. However, the webhook must be called with every user sentence.
Can the webhook response return an empty response and not crash while doing so?
The server returns the response in predefined JSON format known to google assistant. When I set this response to NULL OR when I set the payload part of this response to BLANK, the application crashes.
var simpleChatResponse = {
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
]
}
}
},
"outputContexts": [
]
};
Actual results: "myAgent1 is not responding" and the application crashes.
No, you can not send an empty response. As the docs state:
The first item in a rich response must be a simple response.

Google Cloud HTTP function by webhook: Request body is missing data

Im integrating the Zoom API with my Firebase app, and to do so I'm relying on Zooms pre-made webhooks to run an HTTP function on my Firebase for various events like "meeting started" and "meeting ended". Zoom API reference: https://marketplace.zoom.us/docs/guides/webhooks
This is the Google Cloud function that the Zoom API is calling:
exports.zoomTestA = functions.https.onCall((req, res) => {
console.log(req);
let data = req.body;
var xmlData = data.toString();
console.log(xmlData);
});
Here is the payload sent by Zoom:
{
"event": "meeting.ended",
"payload": {
"account_id": "LTf-KjgUTR2df-knT8BVEw",
"object": {
"duration": 0,
"start_time": "2019-05-07T14:02:51Z",
"timezone": "",
"topic": "Alexander Zoom Meeting",
"id": "864370042",
"type": 1,
"uuid": "2h/SWVrrQMu7fcbpLUly3g==",
"host_id": "Ty6ykNolSU2k1N4oc0NRcQ"
}
}
This causes this error to appear in my Google Cloud console:
Request body is missing data. { event: 'meeting.ended',
payload:
{ account_id: 'LTf-KjgUTR2df-knT8BVEw',
object:
{ duration: 0,
start_time: '2019-04-30T14:23:44Z',
timezone: '',
topic: 'Alexander\'s Zoom Meeting',
id: '837578313',
type: 1,
uuid: 'WotbHO3RRpSviETStKEGYA==',
host_id: 'Ty6ykNolSU2k1N4oc0NRcQ' } } }
The request body that Zoom sends is not wrapped in in a "data: {}" tag as required by Google Cloud functions. I've found solutions to this problem if you can control the payload here: Dart json.encode is not encoding as needed by Firebase Function .
My problem is that I am unable to alter the request that the Zoom API sends. Is there any way I can still accept the request in my Google Cloud function? Or is there any way to alter the format of the request sent by Zoom? I'm unable to find references for either.
One potential solution would be to set up another server that receives the request by Zoom, format it to Google Cloud functions specifications, and then pass it on to my Google Cloud function. I would however like to avoid stepping out of the Google Cloud eco-system.
Is this problem solvable on the Google Cloud platform?
So I figured it out. In Firebase / Google Cloud functions you can either make HTTP-functions with
functions.https.onCall((req, res) => {
var data = req.body;
and
functions.https.onRequest((req, res) => {
var data = req.body;
The difference seems to be that onCall is made for being used within the Firebase/ Google Cloud functions environment. However if you wan external functions you need to use onRequest as this does not require specific formatting of the payload.
Using onRequest instead solved all my problems.

Cannot fetch internet message headers for some emails

I'm using the Microsoft Graph Client for Node.js to fetch email messages. I'm only interested in the headers. The code is working, but recently I got some errors in fetching internetMessageHeaders via the API.
For some messages, the API doesn't return any data for this field (and the code wasn't checking for this, hence the errors).
I tried to manually run the queries using POSTMAN. Using ?$select=internetMessageHeaders as a query param to only fetch the headers. If I remove the query param, I can fetch the message normally (body, etc.).
I haven't been able to find anywhere in the docs why this would happen.
Any ideas on what it's happening?
Edit: Here is the node.js code I am using
const MicrosoftGraphClient = require("#microsoft/microsoft-graph-client").Client
async function fetchEmailMessageHeaders(id, credentials) {
let client = MicrosoftGraphClient.init({
authProvider: callback => callback(null, credentials.access_token)
});
let req = client.api(id).select("internetMessageHeaders");
let message = await req.get();
return message.internetMessageHeaders;
}
Sample output (value of message var):
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('156751349d3cc68b')/messages(internetMessageHeaders)/$entity",
"#odata.etag": "W/\"CQAAABYAAABcr9US8aH2RIGaOGQZwDg3AAKyfdpk\"",
"id": "AQMkADAwATM0MDAAMS1hZWIxLThjZmYALTAwAi0wMAoARgAAA3wcQrEUgfhHoZ0BD2jmyXYHAFyv1RLxofZEgZo4ZBnAODcAAAIBDAAAAFyv1RLxofZEgZo4ZBnAODcAArJaPEcAAAA=",
"internetMessageHeaders": [
{
"name": "Received",
"value": "from BY2NAM01HT225.eop-nam01.prod.protection.outlook.com (2603:10a6:803:118::39) by VI1PR0301MB2221.eurprd03.prod.outlook.com with HTTPS via VE1PR03CA0050.EURPRD03.PROD.OUTLOOK.COM; Wed, 10 Apr 2019 11:41:55 +0000"
}
...
]
}
The problem is that for some emails, the message does not contain internetMessageHeaders.
I am using an inbox subscription to receive events for new email messages from Outlook. When an event is received I use the API to retrieve the message and extract headers from it.
API reference here
Edit2:
Here is an example JSON output of an event that fails to also retrieve headers:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('53e07bf4-bb6a-4a82-a724-37dadfb1cf11')/messages(internetMessageHeaders)/$entity",
"#odata.etag": "W/\"CQAAABQAAADdeU+v2VzbRpZMSJGral7kAAXJkA==\"",
"id": "AAMkADhmMmVmM2NjLWFhNGMtNDBlYy04NzBkLTg5MmU2OWI0ODU4MgBGAAAAAAALg6E-e6CxRLEbZfrhFaDBBwAzAAMgKF1iTp242t34rFy5AAAAAAAOAAB5l_O62bUUTqTLk6KYrl4sAAGrJcjfAAA="
}
It seems internetMessageHeaders are not set when an email is replied to using outlook.office365.com. I'm also not able to see message headers when inspecting the message using Outlook on Mac.

Getting status of Google Cloud transfer Job

I am using node.js utility of google cloud transfer api to transfer data from s3 bucket to my Google Cloud bucket using
#1
storagetransfer.transferJobs.create(request, function (err, response)
And once it is completed i want to proceed with with some functionality.
To check the status of transfer Job there is an api
#2
storagetransfer.transferOperations.get(request, function(err, response)
which takes
var request = {
// The name of the operation resource.
name: 'transferOperations/my-transfer-operation',
auth: authClient,
};
as parameter.
I cant seem to find what is the value that need to be input'ed in place of "my-transfer-operation"
The response received from "storagetransfer.transferJobs.create" has a data object with {name: 'transferJobs/2469904309496821948'}, but this value is not working for "my-transfer-operation" value.
I need to get value of "my-transfer-operation" which can be used a parameter for getting status of my transfer job using #2 api.
source : https://cloud.google.com/storage-transfer/docs/reference/rest/v1/transferOperations/get
You can use transferOperations.list, which you can test here, putting in the request name : 'transferOperations' and filter : "{"project_id" : "<your-project-id>"}".
The response will contain an array of operations with a structure starting like
{
"operations": [
{
"name": "transferOperations/transferJobs-<id-from-transferJobName>-<another-id>",
"metadata": {
...
"status": "<some-status>", //e.g. IN_PROGRESS
...
},
...
and that long name, containing the id you were trying to use, is what you need to input to transferOperations.get. You can also obtain the status directly from that response, as you see.

Resources