I need to store sesion variable witn PHP y Dialogflow - dialogflow-es

my project is to have a chatbot that can sell electronic device like resistor, diode and so on.
There are many type of resistor and diode
I have my intents in dialogflow so when user choose one item I need to store it into php session variable so when user have finished so I need to restore that items in session variable but it doesnt work
Recieve dialogflow intent that is called "tomar_cantidad"
if (intent_recibido("tomar_cantidad")) {
$modelo = obtener_variables3('modelo');
$cantidad = obtener_variables2('cantidad');
//enviar_texto(print_r($cantidad));
$datos_usuario = array('modelo'=>$modelo,'cantidad'=>$cantidad);
$_SESSION['datos_usuario'][]= $datos_usuario;
enviar_texto(print_r($_SESSION['datos_usuario']));
}
enviar_texto is a method to send information to dialogflow(that is for testing purposes).
I recieve session variable but only store the last item that user choose not all items

The issue is that the PHP $_SESSION variable is tied to an HTTP session, which is usually implemented with an HTTP cookie. But Dialogflow doesn't manage HTTP cookies when it sends messages to a webhook, so each fulfillment call is a new session each time.
You have a few ways you can approach this:
Get the Dialogflow session ID and store the information against this ID
Store any values you want to store between turns in the conversation as a parameter in an Output Context. You should set the lifespan for the Context to a large number, 99 is typical, or re-set this as the Output Context each time. Then, you can read the parameter in the named Context when you need the information.

Related

How to determine which user clicked on a button

I'm sending messages with block elements (buttons) to channel using Slack API. How can I get the username displayed when someone approves or rejects the request? I send the message using chat.postMessage.
You should have interactivity enabled for your app. Since you are using buttons you need to reference how to handle interactive components. Essentially, you need to give your buttons an action_id which is it's unique identifier and will help you determine the source of the action (including the user) when the button is clicked. You will parse the action payload that sent to your app to get the user information you need and use that information in a subsequent call to chat.postMessage.
I was having trouble getting the user with the payload, using body instead worked for me:
In Bolt Python:
#app.action("approve_button")
def approve_request(ack, say, body, payload):
# Acknowledge action request
ack()
user_details = body['user']
username = user_details['name']
.....

Prevent new context after responding with new ones on Dialogflow

I have an intent with webhook and slotfilling enabled for validation and it have 4 parameters marked as required, so my server can validade the parameter value.
The strategy that I'm trying to use is: reset the context for invalid parameter value, so the dialogflow can ask it again.
Here is an example entering an invalid value:
On responding "Brasília" the webhook makes a request to my server. My server knows that is an invalid value and respond with the context presented on the previous image.
This is the result:
Notice that the first 4 context match with the previous image, its everything ok here. But dialogflow adds another context. That context is a request for the next parameter, called "motivo" and if I respond back, the response will be stored on this param. After this, dialogflow prompts back for the "local" param.
The conversation runs like this:
User: I want to register a call
Dialogflow: From where you want to register? Aracaju, CAB, Itabuna or Salvador?
User: Brasília
Dialogflow: Please, describe the reason
User: My network wireless is not working
Dialogflow: From where you want to register? Aracaju, CAB, Itabuna or Salvador?
...
What was supose to be:
User: I want to register a call
Dialogflow: From where you want to register? Aracaju, CAB, Itabuna or Salvador?
User: Brasília
Dialogflow: From where you want to register? Aracaju, CAB, Itabuna or Salvador?
...
What I need to know: Am'I responding with the correct contexts? Is there a way to prevent dialogflow creating this new "registrar_dialog_params_motivo" after responding with a new contexts?
Obs.: I'm using a Nodejs server, responding the webhook as the docs suggests.
Edit 1: I know that I can use an entity for this situation. However there is some cases that I need to make multiple validations on backend to procede, something like an user id, etc.
If the intent “Intent_Name” has some input_context defined already, then you need to set that context again as output_context and reply something like you have entered an invalid location, and please enter again.
If the intent does not have any input_context, then you can simply reply you have entered an invalid location. Please enter again, and your intent should be able to catch that too. However, this can cause problems as well.
What I would recommend is having another intent “Intent_Name_followup” with an input_context as location_validation_failed in the logic. If the location is incorrect, you can set this in the output_context to reply to the user.

Is there an anonymous ID in Actions on Google with Dialogflow?

Is there an anonymous ID in Actions on Google with Dialogflow that I can access using DialogFlow in Node.js?
I don't need to know the Google account of who is using the Action, but I do want to have a unique identifier so that the Action can know when they come back.
Google no longer provides one for you. You will have to generate one when a new user interacts with your webhook and store the generated id in their user storage object.
To identify a new user your just check if they already have an id in their user storage object. For generating the id you can use an library like uuid. https://www.npmjs.com/package/uuid
Uuidv4 is probably the one that you need if you just need a unique id for simple identifications
The original idea from Google was to leverage a field called userStorage, but this feature seems to be borked ATM.
userStorage Documentation:
https://developers.google.com/actions/assistant/save-data
Reddit thread regarding issues:
https://www.reddit.com/r/GoogleAssistantDev/comments/d88z7e/userstorage_saga_continued/
Unless something has changed (I haven't checked on userStorage since I've been busy writing a fix around it) you may be out of luck without Account Linking. Feel free to try userStorage and keep me honest as they may have remedied the situation internally.
Alternatively, if all you need is an identifier or session for a single conversation you can leverage the conversationId which will be unique until the conversation ends.
I've found a possible option...
(When working in DialogFlow in Node.js, most code is in a handler and the parameter is usually called conv. The following assumes that it is inside such a handler.)
On every single call, check for an 'existing' id in the session data and the user storage:
var id = conv.data.MyId || conv.user.storage.MyId || '';
if(!id) {
id = /* make a new Id for this user... a GUID or some other unique id */
conv.user.storage.MyId = id;
}
Once I get the Id from storage or make a new one, it is critical to reassign it to conv.data, since conv.user.storage seems to be reliably provided only on the first call!
// IMPORTANT
conv.data.MyId = id;
/* use the Id as needed */
My code looks up the Id in a firebase database to get details from their last visit.
This seems to be working, but may not be reliable.

How do I save and retrieve information across invocations of my agent in Dialogflow?

I would like my Actions on Google agent to store and retrieve certain pieces of information across invocations - like a cookie. How do I do this?
You have a lot of options on how you want to do this, depending on exactly what you're trying to do. It isn't exactly like a web cookie, although there are similarities.
If you want the equivalent of a session cookie, information that is retained during a single conversation, then your options are
Using the Session ID provided as part of the information sent to you on each invocation and tracking this in your fulfillment.
Storing information you want retained using a Dialogflow context
If you are using the actions-on-google JavaScript library, storing this in the app.data object created for you.
If you want the equivalent of a long-lasting cookie to retain information between conversations then your options are
Using the anonymous User ID provided as part of the information sent to you on each invocation and tracking this in your fulfillment.
If you are using the actions-on-google javascript library, storing this in the app.userStorage object created for you.
Storing it as part of the string in the JSON response under data.google.userStorage.
Some more information about each of these
Session ID
A different Session ID is created for each conversation you have. You can get this Session ID by examining the JSON sent to your webhook in the sessionId parameter.
You can then look this up in a data store of some sort that you manage.
Dialogflow context
Contexts are powerful tools that are available with Dialogflow. You return a context as part of your fulfillment webhook and indicate the name of the context, its lifetime (how many more rounds of the conversation it will be passed back to your webhook), and any parameters associated with the context (string key/value pairs).
Contexts are especially useful in helping determine what intents may be called. You can indicate what contexts must be active for an Intent to be recognized by Dialogflow.
If you're using the actions-on-google node.js library, you can set a context using something like this:
var contextParameters = {
foo: "Something foothy",
bar: "Your local bar."
};
app.setContext( "remember_this", 5, contextParameters );
You need to do this before you call app.ask() or app.tell().
Or you can do the equivalent in the JSON as part of the contextOut block of the response
"contextOut": [
{
"name": "remember_this",
"lifespan": 5,
"parameters": {
"foo": "Something foothy",
"bar": "Your local bar."
}
}
]
The next time your webhook is called, you can fetch this context either by looking at the result.contexts array or by using the app.getContext() or app.getContextArgument() methods in the library.
Using app.data
If you're using the library, Google has done some of the work for you. The app.data object is created for you. Any values you set in the object are available for the lifetime of the session - you just read them in later calls to your webhook.
(Under the covers, Google uses a context for this, so there is no magic. The two work together and you're free to do both.)
Anonymous UserID
When a user first uses your action, a user ID is generated. This ID doesn't give you access to any specific information about them, and isn't used for any other action, but every time you see it, you can be assured that it was the same user that used it on a previous occurrence. Just like a cookie, however, the user can reset it and a new ID will be generated for them for your action.
You get this from the JSON at originalRequest.user.userId or by using app.getUser().userId. Once you have it, you'd use a data store of some sort to store and retrieve information about this user.
Using app.userStorage
Similar to app.data, there is also an app.userStorage object that is created for you for each user. Any changes you make to this object are saved in between conversations you have with this user.
Unlike app.data, however, this doesn't get stored in a context. It has its own storage method. Which leads to...
Storing it in JSON
If you're not using the actions-on-google library, you still have access to userStorage through the response and request JSON directly. You need to store this as a string, but if you need to store a more complex object, a common method is to stringify it as JSON.
You'll store this value under data.google.userStorage in the response and can retrieve it under originalRequest.data.user.userStorage in the request your webhook receives.
You can save the information in Context with a key value parameter.
SAVING VALUES IN CONTEXT :
agent.set.Context({
name:'context-name',
lifespan: 5,
parameters:{
'parameter-name':'parameter-value'
}
});
GETTING VALUES FROM CONTEXT
agent.getContext('context-name');
For more Details : https://dialogflow.com/docs/contexts/contexts-fulfillment
You could also use a Google Cloud database like BigQuery or Firestore
Sounds like you may want to checkout out Account Linking: https://developers.google.com/actions/identity/account-linking. With account linking you can collect end-user information which you exchange with Google by providing a unique key. This unique key becomes part of every request you receive from Google, so when you get that unique key you lookup the information you collected from the end-user. In your case, you would store credentials or whatever key is required to access the end-user information. After the initial linking, any new data you obtain could be stored along with the original information collected, based on the unique key obtained during account linking.
For this purpose, i just did a node module just for that, in external json file from api call, i need to store and add additional informations to retrieve later. I thing that you can do a lot with this module, Store object, array, json, value, Navigation history?, back to previous page.
It work like localStorage or Cookies.
There's no limit, you can create multiple storage by name (key) an value. It's new and i'm testing it for bugs right now on my own project.
Test on Runkit
On npm
vStorage = require('virtual-storage');
vStorage.set('name', '{title:'Title 1', description:'Descriptions 1'}')
let getStorage_name = vStorage.get('name');
console.log(getStorage_name.title);
vStorage.get('name')

Creating a thumbnail card with buttons in Bot Framework for Node.js without the session object

My bot has a timer job that checks for something every N minutes and sends a reminder to the user.
Since this is a timer job, that means it's outside any dialog and I don't have access to the session object.
The code works fine if I create the reminder message like this:
new builder.Message().text("This is a reminder!");
However, this code does not work because the CardAction requires a session object as a parameter:
var card = new builder.ThumbnailCard()
.title("Reminder")
.text("Hey it's a reminder.")
.images([exclamation_mark_image_url])
.buttons([builder.CardAction.imBack(null, "check", "Check Overdue")]); //should use `session` instead of null here
The error is a 500 Internal Server Error response from the botframework.com server in chat connector.
This is how I send the generate message when the session object is not available:
//`msg` is the message with a card generated in the code above
bot.beginDialog(address, dialog_name, msg, function (err) {
//nothing
});
How can I create a ThumbnailCard with a button without a session object?
What you can do is store the address of the user, and then use bot.loadSession(storedAddress, function (err, session) {}); This will generate the session object based on the passed in address. In its callback you can use the session object to send messages. I've used the method on a webhook to alert users when certain events are occurring.
Depending on how you're storing the timer/alarm, you can also store the user's last session.message.address with that data. I haven't worked on the implementation of such a bot, but the next part would be adding a job/method that checks a list of alarms continuously/periodically and then sends the message to the user when their alarm is triggered.

Resources