dialogflow v2 extracting parameters in fullfillment - dialogflow-es

i am using my dialogflow over facebook messenger and passing a parameter. i am able to extract it but not sure why it is not a string.
the code looks like below
function botHandler(agent) {
console.log("inside bot handler request body is:" +
JSON.stringify(request.body.queryResult.parameters));
const adParams = request.body.queryResult.parameters;
let state = adParams.stateName;
state = state.toString().toUperCase()
the error it throws is
TypeError: state.toString(...).toUperCase is not a function
at botHandler (/srv/index.js:52:30)
at WebhookClient.handleRequest (/srv/node_modules/dialogflow-fulfillment/src/dialogflow-fulfillment.js:303:44)
at exports.dialogflowFirebaseFulfillment.functions.https.onRequest (/srv/index.js:114:9)
at cloudFunction (/srv/node_modules/firebase-functions/lib/providers/https.js:57:9)
at /worker/worker.js:783:7
at /worker/worker.js:766:11
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
the value is there but not sure why toString fails

toString() is not failing (tho it probably is unnecessary, since it is likely a string already).
Your method toUpercase() is failing because you have a typo in "uppercase". It should have two "p"s, not one. toUppercase().
That said, as Mathais noted, you should make sure you have the stateName parameter first.

I would suggest extracting parameters like this in your fulfillment:
function botHandler(agent) {
let state = agent.parameters["stateName"];
let uState = state.toUpperCase();
let answer = "So you live in " + uState + "?";
agent.add(answer);
}
And you can check if the parameter is present this way:
if (agent.parameters["stateName"]) {
//do stuff here
}
Hope this helps!

Related

Can i build an event object myself in Google Script App?

I bought a 3rd party google app script to use. However, it can only be called with onEdit method and their codes are private that i cannot make change. Also, what i need is based on time-trigger instead of onEdit-trigger. Thus, I tried to build my own event to trigger the function:
// This function work well and can call the 3rd Party App Script
// It is triggered by onEdit googlesheet, which works well
function funcOnEdit(e) {
3rdPartyApp.funcOnEdit(e));
}
// Below is the jsontostring result of the event e
// {authMode:"FULL",oldValue:"false",range:{columnEnd:6,columnStart:6,rowEnd:3,rowStart:3},source:{},triggerUid:"xxx",user:{email:"xxxx#gmail.com",nickname:"xxxx"},value:"TRUE"}
So I build a similar event object which triggered by time to make it happened.
function funcOnTimeTrigger(e) {
var e1 = {authMode:"FULL",oldValue:"false",range:{columnEnd:6,columnStart:6,rowEnd:3,rowStart:3},source:{},triggerUid:"xxx",user:{email:"xxxx#gmail.com",nickname:"xxxx"},value:"TRUE"};
e1.triggerUid = e.triggerUid;
3rdPartyApp.funcOnEdit(e1));
}
Unfortunately, I cannot find any document and reference code to build an "onEdit" event. Thats why, I tried find the object/class myself.
function getObjType(obj) {
var type = typeof(obj);
if (type === "object") {
try {
// Try a dummy method, catch the error
type = obj.getObjTypeXYZZY();
} catch (error) {
// Should be a TypeError - parse the object type from error message
// type = error.message.split(" object ")[1].replace('.','');
type = error.message;
}
}
return type;
}
// Below function is triggered by onEdit
function funcOnEdit_checker(e) {
getObjType(e);
}
// Unfortunately, it cannot show the object name or classname
I have no idea what to do next, may i know if it is possible to build an event class/object ourselves in Google Script App? Can anyone give some hints on how to do so? or it is not possible?
I want to create the event-obj "developers.google.com/apps-script/guides/triggers/events" manually and pass the event "e" to 3rdPartyApp.funcOnEdit function. Is it possible to do so?
Reference:
https://developers.google.com/apps-script/guides/triggers/installable
Thanks #Cooper idea, who share same thought as me.
And finally I found the result # Explain purpose of `e` event parameter in onEdit
Below is my answer (not yet optimized but work):
function funcOnTimeTrigger(e) {
var e2 = {}
e2["authMode"] = ScriptApp.AuthMode.FULL
e2['user'] = "me";
e2['range'] = SpreadsheetApp.getActive().getSheetByName("XXXXXX").getRange(5,3).activate();
e2.range.columnStart = 5;
e2.range.columnEnd = 5;
e2.range.rowStart = 3;
e2.range.rowEnd = 3;
e2['source'] = SpreadsheetApp.getActive();
e2['oldValue'] = "old";
e2['value'] = "new";
// Run The Program
3rdPartyApp.funcOnEdit(e2);
}

Unable to find the source of error dialogflow fulfillment

I am trying to create intent in which when the user sends a parameter, then it should be checked in the database that is already there or not. If it already exists user gets a response A and if not it is added to the database, & the user gets response B. I am using Axios to make the API calls. But the code is not working.
I am getting a following errors in the console.
TypeError: Cannot set property 'response' of undefined
at axios.get.then.response (/srv/index.js:33:18)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)"
Show matching entries
Hide matching entries
Add field to summary line
I am not a professional, I am doing all this coding by learning from online tutorials and youtube videos Please help.
function idHandler(agent) {
const idcard = agent.parameters.idcard;
const idvalue = ' ';
const idname= ' ';
axios.get('API' + idcard)
.then(response => {
this.response = response.data;
idvalue = this.response[0].IDcard;
idname = this.response[0].Name;
});
if (idcard === idvalue) {
const ans = 'Name of ' + idname + ' is already present in the List';
agent.add(ans);
} else {
const data = [{
idcard: idcard
}];
axios.post('API', data);
}
}
You have a few issues with both how to code for Dialogflow, and how to express some of the syntax correctly. Some of that is because it looks like you're mixing code that expects Promises with code that doesn't.
The axios library is meant to work with Promises - the get and post methods both return Promises. So you can either work with them by using an await method, or by using the .then() method that the returned Promise has. You may want to look up details of both.
Additionally, Dialogflow requires that you either return the Promise, or that your handler be an async function (which will return a Promise for you).
If you're using the .then() approach, however, then everything you do that relies on the call to axios must be done inside the .then() block and you must return that Promise. If you use await, then your function must be declared as an async function. (You can probably mix the two - but don't.)
So that part of your code might look something like:
return axios.get( url )
.then( response => {
// Do EVERYTHING in here
});
And inside the then() code block is where you would extract the values you want, call agent.add() with the message, and possibly make the API call to add data.
While this didn't get flagged as an error, you are trying to assign a value to a const after it is initially set. This is an error. Those should probably be declared using let instead.
Your error looks like it is saying that this is undefined. Which seems... odd. But also not really an issue since you probably don't need to be using this for most of what you're trying to do. If you scope the variables with let, then they should be available for the life of the function.

How to fix 'TypeError: Cannot read property 'tag' of undefined' error in NodeJS

I'm new to coding and I'm trying to set up a bot on Discord... I want the bot to message the user with an embed, similar to one I used earlier in my project that works just fine. I changed the code a bit and it won't register this one, even though the other code works just fine. What am I doing wrong? The error message reads:
TypeError: Cannot read property 'tag' of undefined
at Client.client.on (C:\Users\Tristan\my-bot\pokegrove\index.js:112:29)
at Client.emit (events.js:194:15)
at MessageCreateHandler.handle (C:\Users\Tristan\my-bot\pokegrove\node_modules\discord.js\src\client\websocket\packets\handlers\MessageCreate.js:9:34)
at WebSocketPacketManager.handle (C:\Users\Tristan\my-bot\pokegrove\node_modules\discord.js\src\client\websocket\packets\WebSocketPacketManager.js:103:65)
at WebSocketConnection.onPacket (C:\Users\Tristan\my-bot\pokegrove\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:333:35)
at WebSocketConnection.onMessage (C:\Users\Tristan\my-bot\pokegrove\node_modules\discord.js\src\client\websocket\WebSocketConnection.js:296:17)
at WebSocket.onMessage (C:\Users\Tristan\my-bot\pokegrove\node_modules\ws\lib\event-target.js:120:16)
at WebSocket.emit (events.js:189:13)
at Receiver._receiver.onmessage (C:\Users\Tristan\my-bot\pokegrove\node_modules\ws\lib\websocket.js:137:47)
at Receiver.dataMessage (C:\Users\Tristan\my-bot\pokegrove\node_modules\ws\lib\receiver.js:409:14)
I've tried changing parts of the original code around to fit my needs. I've searched for other issues pertaining to the error code I've received, but I can't find anything that's specific to my issue... Here's the original code I was using (this one works fine):
client.on("guildMemberAdd", (member) => { // Check out previous chapter for information about this event
let guild = member.guild;
let memberTag = member.user.tag;
if(guild.systemChannel){
guild.systemChannel.send(new Discord.RichEmbed() // Creating instance of Discord.RichEmbed
.setTitle("A new user joined") // Calling method setTitle on constructor.
.setDescription(memberTag + " has joined the adventure") // Setting embed description
.setThumbnail(member.user.displayAvatarURL) // The image on the top right; method requires an url, not a path to file!
.addField("Members now", member.guild.memberCount) // Adds a field; First parameter is the title and the second is the value.
.setTimestamp() // Sets a timestamp at the end of the embed
);
}
});
Ignore the "addfield" on this code, I'm still changing that (it also has the same issue without this added, so it doesn't seem to matter). Here is the code I changed a bit (that won't work):
client.on('message', (member) => { // Check out previous chapter for information about this event
let guild = member.guild;
let memberTag = member.user.tag;
if(prefix + "donate"){
message.author.send(new Discord.RichEmbed() // Creating instance of Discord.RichEmbed
.setTitle("Thank you for your support!") // Calling method setTitle on constructor.
.setDescription(memberTag + ", with your [donation](https://www.paypal.me/pokegroveofficial), we can continue to better PokéGrove (and buy some more Poké treats!)") // Setting embed description
.setThumbnail("http://i68.tinypic.com/2ltq9nt.jpg") // The image on the top right; method requires an url, not a path to file!
.setImage("http://i68.tinypic.com/2ltq9nt.jpg")
.addField("Members now", member.guild.memberCount) // Adds a field; First parameter is the title and the second is the value.
.setTimestamp() // Sets a timestamp at the end of the embed
);
}
});
I expect the code to send an embedded direct message, and instead, the bot crashes and gives that error. Any help would be really appreciated because I've looked through Google and tried to ask other people for help, but I basically got told, "figure it out."
On this line
let memberTag = member.user.tag;
The property user is missing.
You should add some defensive code to handle this happening, or identify why it’s not there.
Something like
if (member.user && member.user.tag) {
// access tag here
} else {
// doesn’t exist
}
If we're talking about the second piece of code you have, there's no member parameter in a message event. It would be message, and a message doesn't have a user property. That's the source of your error.
client.on('message', message => {
let guild = message.guild;
let memberTag = message.author.tag;
// rest of code
});
Discord.js docs may be helpful.

bluebird Promise.promisifyAll can work while promisify a function of that object fails

I try to promisify SFTPWrapper and hit this problem. I am not sure if it happens to other object or not.
So if I just promisify one SFTPWrapper function, say readdir, bluebird will have unhandledRejection : "Cannot read property 'readdir' of undefined" error. I tried util.promisify, the same error too.
But if promisifyAll(SFTPWrapper) and it work as expected. But why is that ?
---- update -----
The code I use,
var Client = require('ssh2').Client
var conn = new Client()
conn.on('ready', function() {
conn.sftp(async function(err, sftp) {
if (err) throw err
try {
// promisify will have Cannot read property 'readdir' of undefined error
// both bluebird and util have the error
//let readdirAsync = Promise.promisify(sftp.readdir)
let readdirAsync = util.promisify(sftp.readdir)
list = await readdirAsync(remotePathToList)
// Promise.promisifyAll(sftp) work
const sftp2 = Promise.promisifyAll(sftp)
let list = await sftp2.readdirAsync(toRead)
You don't show exactly where that error "Cannot read property 'readdir' of undefined error" occurs. If it occurs on this line of code:
let readdirAsync = util.promisify(sftp.readdir);
Then, the problem is that sftp is undefined. But, it doesn't appear that that is exactly the issue because you say that const sftp2 = Promise.promisifyAll(sftp) does work.
So, I'm guessing that the problem occurs when you try to use readdirAsync. If that's the case, then it's probably because you lost the sftp parent when you did let readdirAsync = util.promisify(sftp.readdir) and that is somehow important to the readdir method implementation. If that is indeed the case, then you can do this:
let readdirAsync = util.promisify(sftp.readdir).bind(sftp);
To make sure the parent object stays bound to the method. Because Bluebird's .promisifyAll() puts the new methods on the original object and you call them as methods on the object, not as plain functions, this binding to the original object happens automatically when you call them as sftp2.readdirAsync(). You could do that also as in:
sftp.readdirAsync = util.promisify(sftp.readdir);
And, then you could call sftp.readdirAsync(...).then(...).catch(...) and they'd be bound appropriately to the sftp object.
P.S. Using if (err) throw err inside an async callback is NEVER good error handling. You literally should never write that line of code inside an async callback unless the caller of that async callback has an explicit handler for that exception (which is usually not the case). All it does is throw an exception into async oblivion with no opportunity for actual error handling anywhere else in your code.

chrome extension storage api syntax

chrome.storage.sync.set({'overlayColor': color});
var get = chrome.storage.sync.get('overlayColor',function());
Why do I get "Uncaught SyntaxError: Unexpected token )" for the 2nd line??
By the way, if I take away the call back function in get function, the error becomes:
extensions::StorageArea:35 Uncaught Error: Invocation of form get(string) doesn't match definition get(optional string or array or object keys, function callback)
at normalizeArgumentsAndValidate (extensions::schemaUtils:115:11)
at StorageArea.self.(anonymous function) [as get] (extensions::StorageArea:35:14)
at HTMLInputElement.changeOverlayColor (chrome-extension://neihdeocppgagfakakclajlmbgognbbc/option.js:9:35)
at Object.fireEvent (chrome-extension://neihdeocppgagfakakclajlmbgognbbc/jscolor.js:240:7)
at Object.dispatchChange (chrome-extension://neihdeocppgagfakakclajlmbgognbbc/jscolor.js:675:9)
at HTMLDocument. (chrome-extension://neihdeocppgagfakakclajlmbgognbbc/jscolor.js:667:8)
The function is missing the curly braces. You will need to replace function() with function() {}
var get = chrome.storage.sync.get('overlayColor',function() {});
The function doesn't return the data so instead of storing the result in a variable, you will want to put the logic needing the values in the callback
chrome.storage.sync.get('overlayColor',function(data) {
// use data here
});
Function is not properly declared. Correct syntax is as following:
chrome.storage.sync.get('overlayColor', function (result) {
var get = result.overlayColor;
});

Resources