Intercept user intent with `routing` middleware - node.js

I'm trying to intercept messages to send to my analytics server.
I'm looking to send it some data such as: messages,intent,resulted dialog.
I tried to use the routing middleware of universalBot in this fashion:
bot.on('routing',(session)=>{
console.log(session.intent);
console.log(session);
})
But it seems like the intent is undefined, and the only way I manage to see it is through triggerAction => onFindAction function.
I can use this method but it seems like a hack, is there a good way to intercept the intent data with middleware?
I'm using the Node.js SDK with botbuilder-apiai

Related

Response from Webhook using NodeJS Client

I built a custom webhook as a fulfillment endpoint for a Dialogflow intent. It works fine when I respond with raw JSON, ie: {'fullfillmentText':'hi'},
but does not seem to work using the "actions-on-google" library.
The code from their website implies this should work:
app.intent('myintent', (conv) => {
conv.close('See you later!');
});
But it does not. Google Home just says my app isn't responding. It might be that as it stands my function (using Fn Project) has to return JSON and if I return JSON as a response that it isn't expecting it fails. Maybe someone can shed some light?
Edit 1:
I'm using a custom webhook using the Fn Project open source functions as a service. Demonstrating how to use the project is my purpose here so I don't want to use inline editor or Google Cloud Functions or firebase or any other default option.
Here's the rest of the code
const fdk = require('#fnproject/fdk');
const request = require('request');
const dialogflow = require('actions-on-google');
const app = dialogflow({
debug: true,
});
fdk.handle(function (input) {
app.intent('myintent', (conv) => {
conv.ask('I could not understand. Can you say that again?');
});
return {'fulfillmentText': 'response from webhook'}
});
Although you are creating the app object, which does the Intent handler processing and such, and registering a handler with it via app.intent(), you're not doing anything to "export" it so app's methods are called when the webhook is triggered. When called, it gets the body of the request and will format the JSON for the response.
If, for example, you were using Firebase functions, you would connect app to be handled through the functions with something like
exports.fulfillment = functions.https.onRequest(app);
But you're not. You're using a different framework.
The library comes with a number of frameworks that are supported out of the box, but the Fn Project isn't one of them. In theory, you can create your own Framework object which will do this for you (the "Frameworks" section of this article discusses it briefly, but doesn't go into details about how to do so).
As you surmise, it may be easiest for you to just read the JSON request and generate the JSON response yourself without using the actions-on-google library. Or you can look into a library such as multivocal to see if it would be easier to leverage its multi-framework support.

When is a conversation started on Facebook? - NodeJS SDK

When a facebook messenger user start a conversation I want to get the data like name, photo, etc ... and send to my API.
But I'm doubtful when I should do this.
It would be in the:
bot.on('conversationUpdate', (session) => {
// On here??
})
Facebook doesn't support the conversationUpdate event. It won't send events when you start a conversation, however you could solve your issue in two different ways.
Create a custom middleware that checks if you already have the userData from Facebook and retrieve it when you don't have it yet.
Create a custom middleware that translates Facebook's callbacks to intents
I already created those for NodeJS, which you can use in your bot. BotBuilder-FacebookExtensions
If you need more guidance, you can read the blogs I wrote about this:
How to retrieve User Data from Facebook /
How to process Facebook Messenger callbacks

How to access 'session.conversationData' while intercepting 'send' hook from middleware?

I have been following the official guidelines while trying to intercept user/bot messages.
bot.use({
botbuilder (session, next) {
logger.info("MESSAGE RECEIVED:" + session.message.text);
next();
},
send (event, next) {
logger.info("MESSAGE SENT:" + event.text);
next();
}
});
While botbuilder hook behaves as expected, send is never called.
At the moment when i will be able to solve this issue, my goal is to have
access to the session object, more precisely to the session.conversationData storage container from the send method middleware.
What have i done ?
i have been following the Logging middleware example and the readme states:
The botbuilder hook on the middleware is an example of ISessionMiddleware. The main advantage of using this hook instead of receive is the access we gain to the session.
and
send and receive hooks use IEventMiddleware. The first argument is the event itself. To see whether an event is a message, check to see if event.type is 'message'.
Currently i have wrapped the session.send in a custom function so i can log the messages which are send by the bot, and another function which logs the user response from inside the dialog. While this solution solves my problem it feels bad ( need to manually update each dialog ) and i am not able to create a generic middleware which could be loaded from a module.
What am i trying to achieve ?
The purpose of my middleware is to intercept user/bot messages and log them to SQL table with the following schema : conversation-id, message-text, timestamp.
conversation-id is stored in session.conversationData storage container, thus why i need to get access to session object from the send hook.
using "botbuilder": "^3.13.1"
You can load the session within the send by calling loadSessionWithoutDispatching:
send: function (message, next) {
bot.loadSessionWithoutDispatching(message.address,function (error,session){
console.log(session.userData);
});
next();
}

Accessing Hapi request id without passing the request object everywhere?

I have a REST API written in Node.js/Hapi and I'm working on adding logging to it and integrating that to a centralized logging service like Splunk.
What I'd like to be able to do is write a simple logging util so that anywhere in the code I can do something like:
LoggingUtil.log('some message');
and the LoggingUtil would be able to figure out which request it pertains to and include that in the actual message that gets logged. That way when I search the logs the request id will tie together all the logs pertaining to a specific request.
I'm not super familiar with the event loop in Node and how I could accomplish this. The only thing I've found that might work is tick-id
I'm not sure exactly what you mean, but I give 2 suggestions based on whether you want logging all the time or just for debugging.
logging all the time example using Hapi's lifecycle method
server.ext('onRequest', (request, reply) => {
console.log(`\n++++++ ${request.raw.req.method} ${request.raw.req.url} ++++++\n`);
reply.continue();
});
onRequest means every time there is a request, this function is called. for mine I made it log the request method and URL. you can observe the request object to get the info you want.
logging only for debugging
basically same logic, pass the request object and access the info you need from there.
In your log function:
log(request) {
console.log(WHATEVER_YOU_NEED)
}

How to use a callback array as the handler for a Sails.js route?

When using Express, it is possible to attach a callback array to a route like this:
app.get('/path', thisIsAnArrayOfFunctions);
And then, when making a request to http://route_to_server/path each function inside thisIsAnArrayOfFunctions is called.
Exactly how does that routing behaviour works in express? is it just an iteration through thisIsAnArrayOfFunctions, passing the arguments req, res and next?
Is it possible to achieve a simple implementation in Sails for this?
I know it works if I attach the routing as an express middleware, but I want to know if there's a solution using the Sails' (version 0.9.8) controller structure.
Thanks in advance.
The Sails-y way of chaining functions to a route is by using policies. The idea is that your controller code should be the last stop in handling your route. Anything that might modify the response (like a login check, or something that could change the params) should be implemented as a policy, which is middleware that can call next or send a response directly. Policies are mapped to controller actions, and multiple policies can be applied to a single action (or to all actions in a controller).
Docs for policies are here.

Resources