Botframework (Node) - dialogData stripping out regex - node.js

Does the BotBuilder Node SDK actively strip out anything that is stored the dialogData object?
For example, I have created a simple loop and I am storing a regex in session.dialogData.questions. When I console log this after storing it, I can see that my regex is stored as expected:
{
validation: /^[0-9]{19}$/,
}
However, when I try and log the same session.dialogData.questions object in the next step of my waterfall, then the regex seems to have been converted into an empty object:
{
validation: {}
}
I presume this a deliberate attempt to prevent XSS and other types of exploitation?
The code for this example can be found below:
const builder = require('botbuilder')
const lib = new builder.Library('FormBuilder')
lib.dialog('/', [
(session, args) => {
session.dialogData.questions = {
validation: /^[0-9]{19}$/
}
console.log(session.dialogData.questions)
builder.Prompts.confirm(session, 'Would you like to proceed?')
},
(session, results) => {
console.log(session.dialogData.questions)
}
])
module.exports.createLibrary = () => {
return lib.clone()
}

Regarding your initial question, no the SDK doesn't actively strip anything out of the dialogData object. Anything that is, except for regexp...
I'm not sure why this is, but for the time being I recommend storing your pattern as a string, '^[0-9]{19}$', and then constructing a new regexp via new RegExp(session.dialogData.questions.validation) when needed.
I tried storing a method to construct a new RegExp using this.questions.validation, but likewise this was also stripped out.
Edit:
Per Ezequiel's comment, this isn't a Bot Framework issue in the end. It is not possible to store non-serializable data inside JSON.

Related

How to add multiline painless code in nodejs

So in my js-code I have this line:
var _script = {
_script: {
script: {
lang: 'painless',
source: `
"""
if(1>2){
params._source.id;
}
else{
params._source.id;
}
"""
`
},
type: 'string',
order: params._source.id
}
}
This will fail. I see in the log this error message:
,\"reason\":\"unexpected token ['\\\"\\\\n if(1>2){\\\\n params._source.id;\\\\n }\\\\n else{\\\\n params._source.id;\\\\n }\\\\n \\\"'] was expecting one of [{<EOF>, ';'}].\"}}}]},
I have tried first to have without tilde-character. And then it also fails.
I then tried to have tilde at the beginning, something like:
var _script = `{
Thing is that the final json that will be sent to elastic is not shown in the code above. So "_script" is only a little part of all the json.
I was wondering if I added the tilde at the very beginning and end of the whole json. Maybe it could work? I need to work it out where it is.
But just in theory: do you think the problem is there? Putting the tilde around all the json? Or is it something else?
The triple " is not valid JSON, it only works internally to the Elastic stack (i.e. from Kibana Dev Tools to ES).
The way I usually do it from Node.js is to add each line to an array and then I join that array, like this:
const code = [];
code.push("if(1>2){");
code.push("params._source.id;");
code.push("} else {");
code.push("params._source.id;");
code.push("}");
source = code.join(" ");
It's not super legible, I admit. Another way is to use stored scripts so you can simple reference your script by ID in Node.js.

How to get entity from the argument and create if condition in Dialogflow Inline editor for fulfilment

I am completely new to Dialogflow and nodejs. I need to get the entity value from the argument to the function (agent) and apply if the condition on that. How can I achieve this?
I am trying below but every time I get else condition become true.
I have created an entity named about_member.
function about_member_handeller(agent)
{
if(agent.about_member=="Tarun")
{
agent.add('Yes Tarun');
}
else
{
agent.add("No tarun");
}
}
Please help.
In such cases, you may use console.log to help unleash your black box, like below:
function about_member_handeller(agent) {
console.log(JSON.stringify(agent, null, 2));
if(agent.about_member=="Tarun") {
agent.add('Yes Tarun');
}
else {
agent.add("No tarun");
}
}
JSON.stringfy() will serialize your json object into string and console.log will print the same on the stdOut. So once you run your code this will print the object structure for agent and after which you will know on how to access about_member. Because in the above code it's obvious that you are expecting about_member to be a string, but this code will let you know on the actual data in it and how to compare it.
To get the parameter you can use the following;
const valueOfParam = agent.parameters["parameterName"];

Watson Conversation API says: 'Patterns are defined but type is not specified.'

I am trying to call the updateValue method of the Watson Conversation API using the Watson SDK for Node.js. The request updates the patterns of the patterns-type entity value.
My request fails with a 400 Bad Request and the message:
[ { message: 'Patterns are defined but type is not specified.',
path: '.patterns' } ],
Here is the code I'm using to call the API - pretty standard.:
let params = {
workspace_id: '<redacted>',
entity: 'myEntityType',
type: 'patterns', // tried with and without this line
value: 'myCanonicalValue',
new_patterns: ['test'],
};
watsonApi.updateValue(params, (error, response) => {
if (error) {
console.log('Error returned by Watson when updating an entity value.');
reject(error);
} else {
resolve(response);
}
});
Actually, what the request is doing is trying to delete a pattern from the pattern list. Since there is no endpoint for deleting patterns, I fetch the list of patterns, delete the one I need to delete from the pattern list, and send the now-reduced patterns list via the updateValue method. In the above example, imagine the pattern list was ['test', 'test2']. By calling updateValue with ['test'] only, we are deleting the test2 pattern.
I am using a previous API version but I've also tested it in the Assistant API Explorer and the version 2018-07-10 results in the same problem when sending a raw request body formed as follows:
{
"patterns": ["test"]
}
Am I doing something wrong or did I forget a parameter?
It's not a bug, but it is a non-intuitive parameter name. The service accepts a type parameter and the Node SDK has a wrapper parameter called new_type. If you are using this to update patterns and not synonyms (the default), then you need to specify new_type as "patterns" even though the parameter is listed as optional.
This appears to be a bug in Watson Conversation Node.js SDK.
To avoid this, always add new_type: 'patterns' to the params:
let params = {
workspace_id: '<redacted>',
entity: 'myEntityType',
new_type: 'patterns',
value: 'myCanonicalValue',
new_patterns: ['test'],
};
I read the Watson Assistant API for updateValue the following way:
The new_type parameter is not required, valid values are synonyms or patterns. However, if you don't provide that parameter, the default kicks in. According to the documentation the default is synonyms. This would explain the error when you pass in patterns.

Cannot save in chrome Storage

I use the following code to load and save a value in chrome.storage:
$(document).ready(function()
{
$( "#filterPlus" ).click(function()
{
SaveSwitch("plus1","#filterPlus","plus1");
});
}
function SaveSwitch(propertyName, imageId, imageSrc)
{
chrome.storage.sync.get(propertyName, function (result) {
var oldValue = result.propertyName;
alert('GET:old='+oldValue);
if (oldValue==null)
{
oldValue=false;
}
var newValue=!oldValue;
chrome.storage.sync.set({propertyName: newValue}, function()
{
alert('SET:'+newValue);
});
});
}
When I run through this method, the first alert shows:GET:old=undefined, the second alert shows:SET:true just like expected. But when calling that method again with the same parameters the first alert AGAIN shows GET:old=undefined instead of GET:old=true which I expected.
It is the same behaviour when I use storage.local instead of storage.sync
"storage" is in the manifest's permissions. The JS is called from the options-page of my extension-
You're doing .get("plus1", ...) and then later doing .set({"propertyName": newValue}, ...). You are storing under the key "propertyName" but fetching the key "plus1", which has never been set.
Perhaps your misunderstanding is that keys in object literals are themselves literal (even when not quoted), rather than variable identifiers. In that case, you might benefit form reading How to use chrome.storage in a chrome extension using a variable's value as the key name?.

Query value gets quoted automatically before sending it to MongoDB?

The following is confusing me a lot. I have been spending quite a bit of time trying to understand why collection.find() doesn't work with regex passed as an object. The regex match is coming over HTTP wrapped in the body of a POST request. Then I try to gather the query (in string format) and perform the query. The problem seems to be that unless the regex is written inside Node without quotes, it won't work. That is, it must be a literal without quotes.
For example, the following works fine:
var query1 = {
company: {
'$regex': /goog/
}
};
collection.find(query1, {}).toArray(function (err, docs) {
// Got results back. Awesome.
});
However, if the data comes wrapped in an object, it doesn't return anything. I suspect it's because the value gets quoted behind the scenes (i.e. "/goog/"):
// Assume
var query2 = {
company: {
'$regex': query.company
}
};
collection.find(query2, {}).toArray(function (err, docs) {
// Got nothing back.
});
I have tested it with the mongo shell and I can confirm the following:
// Returns 5 results
db.getCollection("contacts").find( { "company": /goog/ } )
// Doesn't match anything
db.getCollection("contacts").find( { "company": "/goog/" } )
Furthermore, I just discovered the following: if I write the value with quotes
// Works fine
var companyRegex = {'$regex': /goog/};
var query3 = {
company: companyRegex
};
So technically, a "literal" regex without quotes wrapped in an object works fine. But if it's a string, it won't work. Even after trying to replace the double-quotes and single-quotes with nothing (i.e. essentially removing them.)
Any idea how can I get the regex match be passed verbatim to find()? I've researched it, finding lots of potential solutions, alas it's not working for me.
Thanks in advance!
Let me focus on one line of your post. This is where the problem might be:
The regex match is coming over HTTP wrapped in the body of a POST request.
This seems problematic because:
The only structures that survive serialization between client/server are:
boolean
number
string
null *
objects and arrays containing these basic types
objects and arrays containing object and arrays [of more obj/array] of these basic types
Regexp, Date, Function, and a host of others require reconstruction, which means
passing a string or pair of strings for the match and option components of the Regexp and running Regexp() on the receiving end to reconstruct.
Regexp gets a bit messy because Regexp.toString() and Regexp() do not appear to be inverses of each others: /someMatch/.toString() is "/someMatch/" but RegExp("/someMatch/") is //someMatch// and what was needed instead to rebuild the regexp was just RegExp("someMatch"), which is /someMatch/. I hope this helps.
JSON.stringify(/someMatch/) is {} (at least on Chrome).
So instead of trying to build a general transport, I recommend re instantiating a particular field as a regexp.
* Irrelevant note: (null is fine but undefined is peculiar. JSON won't stringify undefineds in objects and turns undefined into null in Arrays. I recognize this isn't part of your problem, just trying to be complete in describing what can be serialized.)

Resources