node.jsfirebasegoogle-cloud-firestoredialogflow-esdialogflow-es-fulfillment

"Unhandled rejection" message when trying to display data from Firestore Database in Dialogflow payload


I'm new at this & I've read numerous similar articles but none worked for me. I really need close assistance. I'm developing a chatbot using Dialogflow & using the Fulfillment Inline Editor. I wanted an intent where when user enters "Read db" the readDB() function will be triggered and the data from database will be stored in a custom payload. Here is my code:

'use strict';
 
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const {Payload} = require("dialogflow-fulfillment");

const serviceAccount = {
  "type": "service_account",
  "project_id": xxx,
  "private_key_id": xxx,
  "private_key": xxx,
  "client_email": xxx,
  "client_id": xxx,
  "auth_uri": xxx,
  "token_uri": xxx,
  "auth_provider_x509_cert_url": xxx
  "client_x509_cert_url": xxx
};

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://repro-ljcq.firebaseapp.com/"
});
const db = admin.firestore();
db.settings({timestampsInSnapshots: true});
 
process.env.DEBUG = 'dialogflow:debug'; 
 
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
  const agent = new WebhookClient({ request, response });
    
  function displayDB(){
    return admin.firestore().collection('ICR').doc(sessionID).get()
      .then(doc => {
      data = doc.data();
      const payload = {
          "accordion": {
            "title": "Individual Client Record",
            "group": data.groups,
            "age":  data.age,
            "birthdate": data.birthdate,
            "name": data.fullname,
            "phonenumber": data.contactnumber,
            "address": data.address,
            "sex": data.sex,
            "civilstatus": data.civilstatus
          }
        };
        agent.add(new Payload(agent.UNSPECIFIED, payload, {rawPayload: true, sendAsMessage: true}));
    });
  }

  let intentMap = new Map();
  intentMap.set('ReadDB', displayDB);
  agent.handleRequest(intentMap);
});

This is what my Database Structure looks like.

Firestore Database Structure

In my client-side app, it works fine when I use dummy values. This is what it was supposed to look like.

Chatbot Response in Frontend

I can view the data in the logs, but receive "unhandled rejection" error message whenever I try to put it in the payload. Here is the logs:

I don't know whether this is from the wrong execution of the payloads or because of the timeout (retrieving data from firebase takes longer than 5s that it reaches Dialogflow timeout)

Google Cloud Console

Dialogflow 5s Response Time

I really need help :/


Solution

  • Found the answer! Had to restructure the promise into something like this and upgrade my dependencies.

    index.js

    return admin.firestore().collection('ICR').doc(sessionID).get().then((doc) => {
          const data = doc.data();
          console.log(data);
          return data;
        }).then(data => {
          if (data){
            payload = {
              "accordion": {
                "filename": sessionID,
                "title": "Individual Client Record",
                "name": data.fullname,
                "age":  data.age + " years old",
                "sex": data.gender,
                "civilstatus": data.civilstatus,
                "birthdate": data.birthdate,
                "phonenumber": data.phonenumber,
                "group": data.group,
                "address": data.address
              }
            };
            agent.add(new Payload(agent.UNSPECIFIED, payload, {rawPayload: true, sendAsMessage: true}));
          } else {
            //do something
          }
        }).catch(err => {
          console.log(`Error fetching to Firestore.`);
        });
    

    package.json

    {
      "name": "dialogflowFirebaseFulfillment",
      "description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
      "version": "0.0.1",
      "private": true,
      "license": "Apache Version 2.0",
      "author": "Google Inc.",
      "engines": {
        "node": "10"
      },
      "scripts": {
        "start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
        "deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
      },
      "dependencies": {
        "actions-on-google": "^2.5.0",
        "firebase-admin": "^7.0.0",
        "firebase-functions": "^2.2.0",
        "dialogflow": "^0.8.0",
        "dialogflow-fulfillment": "^0.6.1"
      }
    }
    

    Code highly influenced from mikkipastel.