0
votes

So I'm trying to make a google action using Dialogflow that requires an external API. I've always used jQuery .getJSON() to make API calls, so I had no idea how to do this. After searching this up online, I found a way to do this using vanilla javascript (I also tested the way on my website and it worked fine). The code for that is below:

function loadXMLDoc() {
  var xmlhttp = new XMLHttpRequest();

  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == XMLHttpRequest.DONE) {
      console.log(xmlhttp.responseText);
    }
  };

  xmlhttp.open("GET", "https://translate.yandex.net/api/v1.5/tr.json/translate?lang=en-es&key=trnsl.1.1.20190105T052356Z.7f8f950adbfaa46e.9bb53211cb35a84da9ce6ef4b30649c6119514a4&text=eat", true);
  xmlhttp.send();
}

The code worked fine on my website, but as soon as I added it to the Dialogflow, it would give me the error

XMLHttpRequest is not defined

Obviously that happened because I never defined it (using var), except it worked without me doing anything. So then, I tried adding this line

var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;

to the code, and it stopped giving me the error (because I defined XMLHttpRequest). But then, my code wouldn't work.

TL;DR: How can I make an external API call using Dialogflow fulfillment?

2

2 Answers

1
votes

You can use https. But make sure that you upgrade to Blaze Pay(or any other plans) to make external API calls, else you will receive an error such as

Error:
Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions.

Code to make external api call,

// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
"use strict";

const functions = require("firebase-functions");
const { WebhookClient } = require("dialogflow-fulfillment");
const { Card, Suggestion } = require("dialogflow-fulfillment");
const https = require("https");

process.env.DEBUG = "dialogflow:debug"; // enables lib debugging statements

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(
  (request, response) => {
    const agent = new WebhookClient({ request, response });
    console.log(
      "Dialogflow Request headers: " + JSON.stringify(request.headers)
    );
    console.log("Dialogflow Request body: " + JSON.stringify(request.body));

    function getWeather() {
      return weatherAPI()
        .then(chat => {
          agent.add(chat);
        })
        .catch(() => {
          agent.add(`I'm sorry.`);
        });
    }

    function weatherAPI() {
      const url =
        "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";

      return new Promise((resolve, reject) => {
        https.get(url, function(resp) {
          var json = "";
          resp.on("data", function(chunk) {
            console.log("received JSON response: " + chunk);
            json += chunk;
          });

          resp.on("end", function() {
            let jsonData = JSON.parse(json);
            let chat = "The weather is " + jsonData.weather[0].description;
            resolve(chat);
          });
        });
      });
    }

    function welcome(agent) {
      agent.add(`Welcome to my agent!`);
    }

    function fallback(agent) {
      agent.add(`I didn't understand`);
      agent.add(`I'm sorry, can you try again?`);
    }

    let intentMap = new Map();
    intentMap.set("Default Welcome Intent", welcome);
    intentMap.set("Default Fallback Intent", fallback);
    intentMap.set("Weather Intent", getWeather);
    agent.handleRequest(intentMap);
  }
);
0
votes

This article is a diamond! It really helped to clarify what's going on and what's required in Dialogflow fullfilments.

A small suggestion is to gracefully catch the error in the connection to the webservice:

      function weatherAPI() {
        const url = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";

        return new Promise((resolve, reject) => {

            https.get(url, function(resp) {
                var json = "";
                resp.on("data", function(chunk) {
                    console.log("received JSON response: " + chunk);
                    json += chunk;
                });

                resp.on("end", function() {
                    let jsonData = JSON.parse(json);
                    let chat = "The weather is " + jsonData.weather[0].description;
                    resolve(chat);
                });

            }).on("error", (err) => {
                reject("Error: " + err.message);
            });

        });
      }