Get intents, entities, contexts and all data - javascript

In the case, the actually conversation-simple have one function with all the values, but the function update every time if flows conversation.
I want create one function or other form to be able to capture all that data that is currently on the data.
In the case have Intents, context, entities, etc.
conversation.message(payload, function(err, data) {
if (err) {
return res.status(err.code || 500).json(err);
}
return res.json(updateMessage(payload, data));
});
});
The data inside updateMessage parameter have all I need, but if I create other function and try get this values, does not work.
In the case I use the values and get with app.js for open some REST webservice.
I try it:
function login (req, res) {
numberOrigin = null;
sessionid = null;
var dataLogin = {
data: { "userName":"xxxxx","password":"xxxxx","platform":"MyPlatform" },
headers: { "Content-Type": "application/json" }
};
client.registerMethod("postMethod", "xxxxxxxxxxxxxxx/services/login", "POST");
client.methods.postMethod(dataLogin, function (data, response) {
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
var re = /(sessionID: )([^,}]*)/g;
var match = re.exec(data);
var sessionid = match[2]
console.log(sessionid);
}
});
}
function openRequest(data, sessionid, numberOrigin ){
//console.log(data); dont show the values.. show the data response of login
var dataRequest = {
data: {"sessionID": sessionid,
"synchronize":false,
"sourceRequest":{
"numberOrigin":numberOrigin,
"description": JSON.stringify(data.context.email) } },
headers: { "Content-Type": "application/json" }
};
numberOrigin +=1;
client.post("xxxxxxxxxxxxxxxxxx/services/request/create", dataRequest, function (data, response) {
if(Buffer.isBuffer(data)){
data = data.toString('utf8');
console.log(data);
}
});
}
function updateMessage(res, input, data, numberOrigin) {
var email = data.context.email; // this recognize but this function is responsible for other thing
if (email === 'xxxxxxxxxxxx#test.com') {
console.log(data);
login(data);
openRequest(data, sessionid, numberOrigin)
}
}
In case, I just want get the values with my app.js for use inside REST. I got it with ajax but everything on the client side (index.html), and that made me show my credentials, so I decided to do it in REST for security my code..
If have some form to solved this, please let me know.
If have other form to do it, I'll be happy to know.
Thanks advance.

The issue is likely that you need to write to the response object res.. In the updateMessage function the response is passed in. In order for data to be sent back to the browser you need to write to the response. I have a demo app which calls the weather channel to get the weather based on an intent, similar to what you are trying to do with your login function. Please take a look at this code
https://github.com/doconnor78/conversation-simple-weather/blob/master/app.js#L130
You will need to pass the original res (response) object into the appropriate function and then write data to the response (res) once you get it from the third party service.

Related

Node JS Express how can I send a 404 error if a bad request is made to third party API?

In my Node JS server I have this route handler that sends a request to a third party API to get a username:
app.get('/players/:player', apiLimiter, function(request, response) {
const player = request.params.player;
const api_url = `https://api.com/shards/steam/players?filter[playerNames]=${player}`;
var options = {
method: "GET",
observe: 'body',
};
let apiRequest = https.request(api_url, options, function (res) {
let data = "";
res.on("data", chunk => {
data += chunk;
})
res.on("end", () => {
let objectParsed = JSON.parse(JSON.stringify(data));
response.send(objectParsed);
})
if(!player) {
res.status(404).send("Not found.");
}
})
apiRequest.end();
})
This works fine to get a user that exists. However, if I put in a fake username to my /players page, that page still loads with a 200 status instead of getting a 404 response. The page loads and looks broken because it's not actually getting any data from the API.
I feel like this is a dumb question .. In my research I have found how to handle errors if it's just the route, and not if it's the route dependent on the path parameter as in /players/:player
I found a question that was similar to mine (How to throw a 404 error in express.js?) and I tried using an If statement: if (!player){res.status(404).send("Not found."); } but no dice. Am I using this if statement in the wrong place?
How can I get my Node JS server to respond with a 404 if the user from the database doesn't exist?
You have to check the result of the API call and see if you got valid data back and send the 404 there. I also added a check to make sure something was passed for the player name and send back a 400 (bad request) if there's no player specified at all:
app.get('/players/:player', apiLimiter, function(request, response) {
const player = request.params.player;
if (!player) {
res.status(400).send("No player specified.");
return;
}
const api_url = `https://api.com/shards/steam/players?filter[playerNames]=${player}`;
var options = {
method: "GET",
observe: 'body',
};
let apiRequest = https.request(api_url, options, function(res) {
let data = "";
res.on("data", chunk => {
data += chunk;
})
res.on("end", () => {
let objectParsed = JSON.parse(data);
// test objectParsed here
if (!some condition in objectParsed) {
res.status(404).send("No data for that player name.");
} else {
response.send(objectParsed);
}
});
});
apiRequest.end();
});
Also, you don't want JSON.parse(JSON.stringify(data)) here. Your data is already a string. Just do JSON.parse(data).
FYI, if you use a small http request library such as got(), this code gets a lot simpler as it accumulates the response and parses the JSON for you in one line of code as in:
let data = await got(options).json()

Sending data from NodeJS to the client by using Ajax calls

I increase a value at the server by running an Ajax call and want to update my UI after doing this
function increaseHitpoints(){
$.ajax({
type: 'GET',
url: 'http://localhost:8888/incHp/2312'
}).done(function (data) {
$("#txtHitpoints").html(data);
});
}
In my app.js I read a JSON file, manipulate the value, write it back to the file and return it to the client
app.get('/incHp/:id', function (req, res) {
var database = './database.json';
fs.readFile(database, 'utf8', function (err, data) { // read the data
var json = JSON.parse(data);
var users = json.users;
var hitpoints;
users.find(u => {
if (u.id === Number(req.params.id)) { // get the user by id
u.hitpoints++;
hitpoints = u.hitpoints;
}
});
json = JSON.stringify(json);
fs.writeFile(database, json, (err) => { // update the JSON file
// -> missing part here <-
});
});
});
what do I have to pass into the missing part if I want to return the new value? The new value would be hitpoints
I tried res.send(hitpoints); but it seems this function wants to return a status code, not a value.
If you send a numerical value, it will be observed as an HTTP response code
https://expressjs.com/en/api.html#res
But you can send your hitpoints as a string res.send(hitpoints.toString())or as json res.send({hits: hitpoints});
Depends on what format you want your response to be. I prefer using JSON. So in JSON case you would do this:
fs.writeFile(database, json, (err) => {
res.status(200).json({yourKey: yourValue});
});
Then you can access the JSON object in your frontend:
$("#txtHitpoints").html(data.yourKey);

Ajax call on $.ajax().complete

I have a problem with jQuery ajax function. I working with API that provides users and RBAC managment. By design this is separated functions, so when i create a user and assign a role for it i should call two requests - first i send 'create user' and it's return a {"success":"true", "id":"[id nuber]"} then i send 'assign role' with params like "{"item":"RoleName", "user_id":"[id from previous request]"}".
There is object "api" which have some methods for work with API. It is a simple wrapper which knocking on www.myurl.api/ and returns json. Because of it may take a long time api object methods takes a handlers that will be run on success and fail. If api now running a request then api.ready == false, otherwise api.aready == true. Result of last request stored in api.data as object.
Problem is that result not saved in api.data in case when two API request cascaded, like:
api.send(params, //params is json for user creation
function(){ //handler on this request result
... //creating another parms for assignment from api.data
api.send(params2, function(){//handler that works if api coorectly creates a new user
... //here i try send a request with params and it fails
})
}
);
code of api.send method:
send: function (entity, request, params, method, handler){
if (!method)
method='POST';
if (request.toLowerCase()=='get')
request = '';
if (request)
request += '-';
api.data = null;
params.apiKey = api.key;
api.ready = false;
api.handler = handler;
$.ajax({
url: this.url+request+ entity,
method: 'GET',
data: params
}).complete(function(msg) {
api.data = JSON.parse(msg.responseText);
if (api.data[0] && api.data[0].meta)
api.data.forEach(function (element, index, array){
element.meta = JSON.parse(element.meta)
});
api.ready = true;
api.handler.call();
});
}
and this is function that calls to create new user
function createUser(){
validateCreateForm();
if (!createValidated )
return;
var values = {
"username": $('#inputUsername').val(),
"password": $('#inputPassword').val(),
"comment": "Added by "+adderUsername
};
api.send('users','add', values, 'POST', function () {
if (api.data.success="true"){
//===========all in this if works ONLY if api works succesfully
//===========and api.data.id is exist and correct
message("success", "Was created username " + values.username);
$('#inputUsername').val('');
$('#inputPassword').val('');
//==========Problem is here
id = api.data.id; //in this var stores id
console.log('api.data.id is ' + id);//undefined, should be some int.
//if write something like id=42 rights will be correcttly assigned for user with id 42
//================================================================
if (!$('#inputRole').val())
return;
api.send('assignments',
'add',
{
"user_id": id,
"item_name": $('#inputRole').val()
},
'POST',
function () {
if (api.data.success="true"){
message("success", "Account was created and permissions granted");
}
else {
message("success", "Inner error. Please, try again later.");
}
}
);
}
else {
message("danger", "Inner error. Please, try again later.");
}
);
}

Passing data from service to controller

I have created a service with the purpose of accessing an API. I need to return data to my controller but am unsure how to do this as I completely new to sails.
My Service:
// API call to get the ID of contact within Get Response with email address
getContact: function(options) {
// establish connection to API
var api = new getResponse(apiKey, apiUrl);
var contact = api.getContactsByEmail(options.email, null, null, function (response) {
JSON.stringify(response);
console.log(JSON.stringify(response));
});
return contact;
},
I know the API call is working as when I log the response I get the correct response:
{"success":true,"data":{"error":null,"id":1,"result":{"sds":{"ip":null,"name":"Full Name","origin":"api","cycle_day":0,"email":"email#email.com","campaign":"id","created_on":"date","changed_on":null}}}}
My Controller:
index: function(req, res) {
var contact = GetresponseService.getContact({email: 'email#email.com'});
console.log(contact);
return res.send(contact);
}
I want to retrieve the ID value but when I log the value of contact I get undefined. I think my problem is related to the scope but not sure.
Can anyone point me in the right direction?
Because you are directly assigning a value from api.getContactsByEmail() which does not return a value.
By the nature of node.js, the function api.getContactsByEmail() gives you callback with the response. You have to get the value from within the anonymous callback function like this:
// API call to get the ID of contact within Get Response with email address
getContact: function(options) {
// establish connection to API
var api = new getResponse(apiKey, apiUrl);
var contact = "";
api.getContactsByEmail(options.email, null, null, function (response) {
contact = response;
JSON.stringify(response);
console.log(JSON.stringify(response));
return contact;
});
}
more ...
In my opinion, its better to return a callback instead of direct return of value.
// API call to get the ID of contact within Get Response with email address
getContact: function(options, callback) {
// establish connection to API
var api = new getResponse(apiKey, apiUrl);
var contact = "";
api.getContactsByEmail(options.email, null, null, function (response) {
contact = response;
JSON.stringify(response);
console.log(JSON.stringify(response));
if(typeof(callback) == "function")
callback(contact);
else
return contact; // return contact if there is callback func.
});
}
You can use it like:
index: function(req, res) {
var contact;
GetresponseService.getContact({email: 'email#email.com'}, function(contactResult) {
contact = contactResult;
console.log(contact);
return res.send(contact);
});
}
Everything looks like it should work, however I think you're running into an issue with this piece
var contact = api.getContactsByEmail(options.email, null, null, function (response) {
JSON.stringify(response);
console.log(JSON.stringify(response));
});
api.getContactsByEmail is asynchronous I assume, so this declarative statement won't work.
Instead declare contact and return it inside the callback, something like:
api.getContactsByEmail(options.email, null, null, function (response) {
JSON.stringify(response);
console.log(JSON.stringify(response));
var contact = response.contacts; //or however you access the contact(s) from the response variable
//You should also be watching for errors in your callbacks, but that's a different topic
return contact;
});
Read up on asynchronous calls in javascript and make sure you have a solid grasp on when data is accessible when using them.

Fetch data on different server with backbone.js

I can't see what the problem with this is.
I'm trying to fetch data on a different server, the url within the collection is correct but returns a 404 error. When trying to fetch the data the error function is triggered and no data is returned. The php script that returns the data works and gives me the output as expected. Can anyone see what's wrong with my code?
Thanks in advance :)
// function within view to fetch data
fetchData: function()
{
console.log('fetchData')
// Assign scope.
var $this = this;
// Set the colletion.
this.collection = new BookmarkCollection();
console.log(this.collection)
// Call server to get data.
this.collection.fetch(
{
cache: false,
success: function(collection, response)
{
console.log(collection)
// If there are no errors.
if (!collection.errors)
{
// Set JSON of collection to global variable.
app.userBookmarks = collection.toJSON();
// $this.loaded=true;
// Call function to render view.
$this.render();
}
// END if.
},
error: function(collection, response)
{
console.log('fetchData error')
console.log(collection)
console.log(response)
}
});
},
// end of function
Model and collection:
BookmarkModel = Backbone.Model.extend(
{
idAttribute: 'lineNavRef'
});
BookmarkCollection = Backbone.Collection.extend(
{
model: BookmarkModel,
//urlRoot: 'data/getBookmarks.php',
urlRoot: 'http://' + app.Domain + ':' + app.serverPort + '/data/getBookmarks.php?fromCrm=true',
url: function()
{
console.log(this.urlRoot)
return this.urlRoot;
},
parse: function (data, xhr)
{
console.log(data)
// Default error status.
this.errors = false;
if (data.responseCode < 1 || data.errorCode < 1)
{
this.errors = true;
}
return data;
}
});
You can make the requests using JSONP (read about here: http://en.wikipedia.org/wiki/JSONP).
To achive it using Backbone, simply do this:
var collection = new MyCollection();
collection.fetch({ dataType: 'jsonp' });
You backend must ready to do this. The server will receive a callback name generated by jQuery, passed on the query string. So the server must respond:
name_of_callback_fuction_generated({ YOUR DATA HERE });
Hope I've helped.
This is a cross domain request - no can do. Will need to use a local script and use curl to access the one on the other domain.

Categories