JavaScript TypeError - javascript

I am getting this a TypeError: Cannot read property '0' of undefined when testing my aws lambda. The code is
'use strict';
const snsPublisher = require('./snsPublisher');
exports.handler = (event, context, callback) => {
//console.log('Received event:', JSON.stringify(event, null, 2));
const message = event.Records[0].Sns.Message;
console.log('From SNS:', message);
callback(null, message);
};
module.exports.snsLamdbaTriggered = (event, context, callback) => {
var topic = event.Records[0].Sns.TopicArn;
var message = event.Records[0].Sns.Message;
console.log(topic + ' ' + message);
callback(null, { message: 'SNS lamdba was triggered from the topic ' + topic + ' with message ' + message , event });
};
When I change the value inside the brackets I still continue to get the same error. Does anyone know where the problem may lie?

When invoking a lambda function using SNS, the function expects an event object that has specific attributes. So, "testing" your lambda function would fail unless you configure your lambda test event to look exactly the same as an SNS event, for example:
{
"Records": [
{
"EventVersion": "1.0",
"EventSubscriptionArn": eventsubscriptionarn,
"EventSource": "aws:sns",
"Sns": {
"SignatureVersion": "1",
"Timestamp": "1970-01-01T00:00:00.000Z",
"Signature": "EXAMPLE",
"SigningCertUrl": "EXAMPLE",
"MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
"Message": "Hello from SNS!",
"MessageAttributes": {
"Test": {
"Type": "String",
"Value": "TestString"
},
"TestBinary": {
"Type": "Binary",
"Value": "TestBinary"
}
},
"Type": "Notification",
"UnsubscribeUrl": "EXAMPLE",
"TopicArn": topicarn,
"Subject": "TestInvoke"
}
}
]
}

Related

Set value of a js file properties from outside of it

I`m new to JS and apologize for asking a primary question!
We have this first.js file as a js class example with:
const {MakeRequest} = require("./Request");
let api;
let token;
let unique_token;
function chat(data, unique_token = null) {
try {
if (api != null && token != null) {
return MakeRequest(token, api, data, unique_token)
} else {
return {
"provider": {
"website": "https://example.com",
"source": "Example"
},
"status": true,
"response": [],
"options": {},
"error": {
"code": 207,
"message": "Token or Api token did not valueted!"
}
}
}
} catch (e) {
return {
"provider": {
"website": "https://example.com",
"source": "Example"
},
"status": true,
"response": [],
"options": {},
"error": {
"code": e.code,
"message": e.message
}
}
}
}
module.exports = {
token,api,unique_token,chat
}
also, I have this second.js file as a executable js file:
const object = require("./first.js")
object.token ="123456"
object.api ="123456"
object.token ="123456"
console.log(object.chat("hello"))
If I run the second.js file, the api variable is undefined and didn`t get the value from second.js, how can I resolve this problem without change the second.js codes!
You can't edit a variable from a scope outside where it was declared.
Consider passing the values as arguments to chat function when you call it.

How do I handle unnamed nodes in my firebase realtime database using javascript?

{
"chats": {
"3q7QDEHAVpU3DhiNyAOKlZY7L0S25rAQ6mD63HRiygVytCutjMfyZr43": {
"messages": {
"-MhP9vpwRKLND9tIBBOT": {
"message": "thanks",
"senderId": "5rAQ6mD63HRiygVytCutjMfyZr43",
"timeStamp": 1629305419888
},
"-MhSZ8z1kObr2W0UOdZK": {
"message": "hello",
"senderId": "3q7QDEHAVpU3DhiNyAOKlZY7L0S2",
"timeStamp": 1629362363332
},
}
},
"3q7QDEHAVpU3DhiNyAOKlZY7L0S2Ud9F8Ke4bZTMu9vMf5GF98jnwng2":
{},
"5rAQ6mD63HRiygVytCutjMfyZr433q7QDEHAVpU3DhiNyAOKlZY7L0S2":
{},
}
}
I want to retrieve data from the real time database but due to unnamed nodes I am not able to capture the data. Please help me?
When I run the function I getting null in console.log:
Path is correct but snapshot shown null in console:
snapshot: null
function selectAllData6() {
var Id1 = this.id;
var Path1 = firebase.database().ref("chats/{senderId}/messages/{receiverId}/message");
Path1.on('value', function(snapshot) {
var message = snapshot.val();
console.log("message: " + message);
console.log("Path1: " + Path1);
console.log("snapshot: " + snapshot.val());
});
}
selectAllData6();

Dialogflow fulfillment not responding to keywords

I am trying to make sense of how the fulfillment works, and I cannot get the responses from the if statements to work. Whenever I write the keyword, the default response I get is Not available.
The webhook for the intent is enabled, the entity is 'hooked' in the intent as well.
What am I missing here?
const functions = require('firebase-functions');
const { dialogflow } = require('actions-on-google');
const app = dialogflow();
const WELCOME_INTENT = 'Default Welcome Intent';
const USER_MESSAGE_ENTITY = 'UserMessage';
app.intent(WELCOME_INTENT, (conv) => {
const userMessage = conv.parameters(USER_MESSAGE_ENTITY).toLowerCase();
if (userMessage == 'hey') {
conv.ask('Hey there');
} else if (userMessage == 'greetings') {
conv.ask('Greetings, how are you');
} else if (userMessage == 'evening') {
conv.ask('Good evening');
}
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
{
"responseId": "8499a8f2-b570-4fb2-9f3c-262bd03db01e-c4f60134",
"queryResult": {
"queryText": "hey",
"action": "input.welcome",
"parameters": {
"UserMessage": "hey"
},
"allRequiredParamsPresent": true,
"intent": {
"name": "projects/wandlee-zad-rekrutacyjne--euol/agent/intents/d76ffc6c-c724-4fa4-8c9b-7178a2d7f9b7",
"displayName": "Default Welcome Intent"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {
"webhook_latency_ms": 76
},
"languageCode": "pl",
"sentimentAnalysisResult": {
"queryTextSentiment": {
"score": 0.2,
"magnitude": 0.2
}
}
},
"webhookStatus": {
"code": 14,
"message": "Webhook call failed. Error: UNAVAILABLE."
}
}
I don't know where you got conv.parameters(USER_MESSAGE_ENTITY).
The parameters of the intent are accessible as a second function argument. It is going to be a map:
app.intent(WELCOME_INTENT, (conv, params) => {
const userMessage = params[USER_MESSAGE_ENTITY].toLowerCase();
// ...
})
``

Google Forms / Apps Script / Hangouts Chat - Bot message content sending individually instead of together

I'm trying to make a Google Hangouts Chat Bot that detects when a form has been filled in, and sends the responses of the most recent form submission to Hangouts Chat using a bot. I have built this off existing code (my JS / GAS knowledge is near zero), mainly based on the GitHub TSFormBot repo. The issue is, it is sending each response invidiually as a different message, instead of 1 single message with all of the content.
For exmaple, a 4 question form causes the bot to send 4 individual replies, with one of the different answers in each. Could you please help me see where I'm going wrong, so I could get the content of all 4 answers in a single response?
Thanks!
Current code:
function postToRoom(e) {
var formResponses = FormApp.getActiveForm().getResponses();
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
var options, options, url;
url = PropertiesService.getScriptProperties().getProperty('WEBHOOK_URL');
if (url) {
try {
payload = {
"cards": [
{
"header": {
"title": "There is a new request!",
"imageUrl": "https://images.emojiterra.com/google/android-10/128px/1f916.png",
"imageStyle": "IMAGE",
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": '<b>'+ (
itemResponse.getItem().getTitle() + ' ' + itemResponse.getResponse())',
}
}
]
},
{
"widgets": [
{
"buttons": [
{
"textButton": {
"text": "GO TO RESPONSE",
"onClick": {
"openLink": {
"url": e.response.getEditResponseUrl()
}
}
}
},
{
"textButton": {
"text": "GO TO FORM",
"onClick": {
"openLink": {
"url": FormApp.getActiveForm().getEditUrl()
}
}
}
}
]
}
]
}
]
}
]
}
options = {
'method' : 'post',
'contentType': 'application/json; charset=UTF-8',
'payload' : JSON.stringify(payload)
};
UrlFetchApp.fetch(url, options);
} catch(err) {
Logger.log('FormBot: Error processing Bot. ' + err.message);
}
} else {
Logger.log('FormBot: No Webhook URL specified for Bot');
}
}
The Form:
The Bot Response
The issue you're having it's because, inside your for loop, you are sending every time your payload using UrlFetchApp.fetch(url, options);, therefore you need to do it in this way:
// Previous stuff
for (var j = 0; j < itemResponses.length; j++) {
// Do something
}
// Do more stuff
UrlFetchApp.fetch(url, options);
Knowing that. The first thing I changed in your code, it was to create a payload object, which would possess a sections attribute that later will be populated.
var payload = {
"cards": [{
"header": {
"title": "TSFormBot",
"subtitle": "Form Notifications Bot",
"imageUrl": "https://raw.githubusercontent.com/techstreams/TSFormBot/master/notifications.png",
"imageStyle": "IMAGE"
},
"sections": []
}
]
};
Having the payload object, I created a function for populating the sections attribute, there you will have the for loop and after filling the object with all the responses, I added the two buttons:
/*
* Build Payload
*
* #param {Object} payload
* #param {ItemResponse[]} itemResponses
* #param {FormResponse} formResponse
*/
function populateCard(payload, itemResponses, formResponse){
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
payload["cards"][0]["sections"].push({
"widgets": [{
"textParagraph": {
"text": itemResponse.getItem().getTitle() + ' ' + itemResponse.getResponse()
}
}
]
});
}
payload["cards"][0]["sections"].push({
"widgets": [
{
"buttons": [
{
"textButton": {
"text": "GO TO RESPONSE",
"onClick": {
"openLink": {
"url": formResponse.getEditResponseUrl()
}
}
}
},
{
"textButton": {
"text": "GO TO FORM",
"onClick": {
"openLink": {
"url": FormApp.getActiveForm().getEditUrl()
}
}
}
}
]
}
]
}
);
return payload;
}
After all that, you will able to send the request using UrlFetchApp.fetch(url, options);. Your postToRoom(e) function would look like this:
/*
* Process Form Submission
*
* #param {Object} e - form submit event object
*/
function postToRoom(e) {
var formResponses = FormApp.getActiveForm().getResponses();
var formResponse = formResponses[formResponses.length-1];
var itemResponses = formResponse.getItemResponses();
formResponse.getEditResponseUrl()
var options, options, url;
url = PropertiesService.getScriptProperties().getProperty('WEBHOOK_URL');
if (url) {
try {
var payload = {
"cards": [{
"header": {
"title": "TSFormBot",
"subtitle": "Form Notifications Bot",
"imageUrl": "https://raw.githubusercontent.com/techstreams/TSFormBot/master/notifications.png",
"imageStyle": "IMAGE"
},
"sections": []
}
]
};
// Call this function to populate the card with the responses
var PopulatedPayload = populateCard(payload, itemResponses, formResponse);
options = {
'method' : 'post',
'contentType': 'application/json; charset=UTF-8',
'payload' : JSON.stringify(payload)
};
UrlFetchApp.fetch(url, options);
} catch(err) {
Logger.log('TSFormBot: Error processing Bot. ' + err.message);
}
} else {
Logger.log('TSFormBot: No Webhook URL specified for Bot');
}
}
Card Response
Docs
I used these docs to help you:
Class FormResponse.
Class Form.
Card Formatting Messages.

Join query with ElasticSearch

I need to do a join query on firebase using elasticsearch,
can anyone help me?
In particular I have two nodes, in the child node I have a field that is the id of the father node and I would like to have as a result all the fields of the father node.
How do I build my index in the code?
In adding, in my client I use elasticsearchclient,
here is an extract of the code to index a node:
var db = admin.database();
var etest = db.ref(type);
etest.on('child_added', createOrUpdateIndex);
etest.on('child_changed', createOrUpdateIndex);
etest.on('child_removed', removeIndex);
function createOrUpdateIndex(snap) {
client.index(index, type, snap.val(), snap.key)
.on('data', function(data) { console.log('indexed', snap.key + data ); })
.on('error', function(err) { console.log('index error ', err); }).exec();
}
function removeIndex(snap) {
client.deleteDocument(index, type, snap.key, function(error, data) {
if( error ) console.error('failed to delete', snap.key, error);
else console.log('deleted', snap.key);
});
}
And to take query results:
var queue = db.ref("search");
queue.child('request').on('child_added', processRequest);
function processRequest(snap) {
console.log('process...... ');
snap.ref.remove(); // clear the request after we receive it
var data = snap.val();
// Query ElasticSearch
client.search(index, data.type, { "query": { 'query_string': {
"query" : data.query
}}})
.on('data', function(results) {
var res = JSON.parse(results);
console.log(JSON.stringify(res.hits));
console.log("TOTAL " + JSON.stringify(res.hits.total));
queue.child('response/'+snap.key).set(results);
})
.on('error', function(error){ console.log("errore"); }).exec();
}
Thank you in advance
There are two ways to store your data.
First is creating a nested doc. This is helpful if you need to perform search on some of the values and need other info only for the display.
PUT /my_index {
"mappings": {
"yourIndex": {
"properties": {
"yourColumn": {
"type": "nested",
"properties": {
"name": { "type": "string" },
"parentNode": { "type": "string" },
"childNode": { "type": "string" }
}
}
}
}}}
Eg.
'str1', 'parent1', 'child1'
'str2' 'parent1', 'child2'
If you need not maintain any hierarchy,
you can simply create 3 separate columns and store like a flat data.
You can specify parent1 id and search for all the docs in both the cases.

Categories