1

I have created a node.js webhook for my facebook messenger bot. The bot is built in dialog flow and the database is connected to firebase. My question when a function is invoked in the webhook to log in, after logging in, I get a userID from the database, which I want to store it somewhere in the code so that userID info is available throughout the user session. I am storing it in a global variable. However, this works fine if only one user is using the bot. If another user is using the bot at the same time, this userID info is shared between users since this is stored in a global variable. How do I solve this? Please help.

var loggedIn = true;
        for (i = 0; i < contexts.length; i++) {
            console.log("Inside contexts for loop");
            //Check for login details context. 
            if (contexts[i].name == "logindetails") {
                if (contexts[0].parameters.loggedIn == "true") {
                    //set this true if found.
                    loggedIn = true;
                }
            }
        }
        if (loggedIn) {
            showUserAccountOptions(sender);
        }   //else start the login flow and once logged in create the 'logindetails' contexts and set the loggedIn parameter as true.
        else {
            //Login 
            login(email, password);

            //Post the logindetails contexts 
            console.log("Not found");
            let url = "https://api.dialogflow.com/v1/contexts?sessionId=" + response.sessionId;
            console.log("URL", url);
            var con = {
                method: 'POST',
                url: url,
                qs: { access_token: '****' },
                headers: {
                    'content-type': 'application/json',
                    'Authorization': 'Bearer' + ' ****'
                },
                body:
                    [
                        {
                            "lifespan": 25,
                            "name": "logindetails",
                            "parameters": {
                                "loggedIn": "true"
                            }
                        }
                    ],
                json: true
            };

            request(con, function (error, response, body) {
                console.log("Inside api request");
                if (error) {
                    console.log("Inside Error", error);
                }
                else{
                    //show user options
                    showUserAccountOptions(sender);
                }

            });

        }

Sending contexts updates to dialogflow:

    let apirespone = let apirespone = {
                "contexts": [
                    {
                      "name": "logindetails",
                      "parameters": {},
                      "lifespan": 5
                    }
                  ]
                }
                    sendToApiAi(sender,apirespone);

function sendToApiAi(sender, text) {

    sendTypingOn(sender);
    let apiaiRequest = apiAiService.textRequest(text, {
        sessionId: sessionIds.get(sender)
    });

    apiaiRequest.on('response', (response) => {
        if (isDefined(response.result)) {
            handleApiAiResponse(sender, response);
        }
    });



    apiaiRequest.on('error', (error) => console.error(error));
    apiaiRequest.end();
}
  • I'm a bit late but you could also store it in your webhook app, in the app.data object. It does the same as the Dialogflow context – Rémi C. Apr 12 '18 at 09:36

1 Answers1

2

Good call! You definitely don't want to store it in a global variable.

Fortunately, Dialogflow offers a good solution for this.

In your webhook, you can save the userID and any other session information you want as part of a Context parameter. You can set this as an Outgoing Context in your fulfillment code with a long lifespan and/or re-save this Context each time your webhook is called. You don't provide anything about the code you're currently using in your webhook, but you can see the documentation for how the Context can be part of your response JSON or using libraries.

To be clear - you can return the Context as part of the JSON in the response. You don't need to make a REST call to set it. Contexts live as long as their lifetime, so once you have set one, it will live for "lifetime" calls during the session, or you can set new ones (or update their lifespan) each time as part of the JSON you return.

On the next call, you'll be passed all the Contexts that are currently valid. You can find the one that stores the state you've previously saved and get the values from the parameters.

Update to respond to your code

You do not need the REST call you're making.

You can return and update the context in your JSON. You don't show it, but I assume you're creating a response, and adding the context might look something like this:

{
  "displayText": "Show something",
  "contextOut":[
    "name": "logindetails",
    "lifespan": 25,
    "parameters": {
      "loggedIn": "true"
    }
  ]
}

At a later point in the conversation, you can resend this in your response to update the information. You might do it like this:

In your loop where you get the info, you might save the entire context:

        var logindetails;
        if (contexts[i].name == "logindetails") {
            logindetails = contexts[i];
            if (logindetails.parameters.loggedIn == "true") {
                //set this true if found.
                loggedIn = true;
            }
        }

You can then change whatever you want in logindetails and when you create the response, do something like this:

{
  "displayText": "Show something",
  "contextOut":[
    loginDetails
  ]
}
Prisoner
  • 49,922
  • 7
  • 53
  • 105
  • Thank you for replying back. Say for instance, I downloaded user data from firebase database and I want to save this info somewhere instead of calling the database again and again. When i tried to save this in the global varialble, the info is shared among all the users who are accessing the bot, which i dont want to happen. How can I achieve this? – Karthik Venkatesh Apr 05 '18 at 22:12
  • Is there a way to edit the context parameters via webhook and also how do I avoid parameters to reset when the intent is triggered? Please do let me know. – Karthik Venkatesh Apr 06 '18 at 07:29
  • I've updated my answer, but can't really help more on specifics since you haven't provided many details (ie - code). I'm not sure what you mean by "avoid parameters to reset". – Prisoner Apr 06 '18 at 10:09
  • Thank you. That helped a lot . All I was trying to do was to save User info after login and have login state as true through out the sessions. I used /contexts post request to post the new context with user info parameters after login. Please let me know if there is any other better way to do. Currently, dialogflow allows only allows post, get and delete request but cannot update in between the conversation. – Karthik Venkatesh Apr 06 '18 at 18:28
  • OH! You don't need to use the /context REST endpoint. Answer updated to clarify. (This is why I was saying that seeing how you did your code would help.) – Prisoner Apr 06 '18 at 19:30
  • I have added the code to the question. I am executing this code when the login intent is triggered. I check if the the "logindetails" context is present. If no, I finish the login flow and post the "logindetails" with parameters to it. If yes, I contiue with other options. Now, if I want to change the values of the parameters in logindetails context, I have delete the context and post it back since /context endpoint doesn't provide update option. You mentioned about the sending the contexts/parameters JSON from the webhook. Can you please tell me how to achieve this? – Karthik Venkatesh Apr 06 '18 at 21:11
  • Is it possible to edit/update the out contexts parameters? If so, please let me know how to achieve this? – Karthik Venkatesh Apr 06 '18 at 21:33
  • Thank you for the update again. I am not setting any output context in the dialogflow. Instead, I post a new context with login info once the user is logged in. Now, if I want to update the parameters in the context I created, how do I do it? – Karthik Venkatesh Apr 06 '18 at 23:09
  • Please check "Sending contexts updates to dialogflow:" section in the question. Is this the right way to send contexts to the dialogflow? I am getting "Json request query property is invalid" error with code 400. Please help. – Karthik Venkatesh Apr 06 '18 at 23:15
  • If you solved the problem, posting another answer explaining what you did may help others with the same problem. – Prisoner Apr 07 '18 at 10:46