How to make a http request to other service in dialogflow fulfillment without firebase?

感情迁移 提交于 2020-04-18 17:00:32

问题


I wrote a node.js fulfillment code to send my messages from Dialogflow to another services (in this code, it is postman) by simply using the http.request function.

"use strict";

const express = require("express");
const bodyParser = require("body-parser");
const https = require('https');
const app = express();

app.use(
  bodyParser.urlencoded({
    extended: true
  })
);

app.use(bodyParser.json())

app.post("/echo", function(req, res) {
    var speech =
    req.body.queryResult &&
    req.body.queryResult.parameters && 
    req.body.queryResult.parameters.echoText
      ? req.body.queryResult.parameters.echoText
      : "Seems like some problem. Speak again.";
    
    function mainFunction(callback){    

    var options = {
      hostname : "postman-echo.com",
      path : "/post",
      method : "POST",
      headers: {
        'Content-Type': 'application/json'
    }
    };

    var body = JSON.stringify({
        message: speech
    });
    
    
    var req = https.request(options, function(res) {
        var respBody = "";
        console.log("Response from server started");
        console.log(`Server status: ${res.statusCode}`);
    });
    
    //Necessary, otherwise a socket hangup error
    req.end(body);
    
    req.on('response', function(res){
        //console.log('STATUS: ' + res.statusCode);
        res.setEncoding('utf8');

        res.on('data',function(chunk){
            var temp = JSON.parse(chunk.toString());
            //console.log('Dit is de response');
            console.log(temp.data.message);
            
            var resp_message = [];
            if (temp.data.length > 1) {
              var i;
              for (i = 0; i < temp.data.length; i++) {
                var resp_message_single = temp.data[i].message;
                resp_message.push(resp_message_single);
              };
              callback(resp_message)
            }
            else{
              var resp_message_single = temp.data.message;
              resp_message.push(resp_message_single);
              callback(resp_message)
            };
        });
    });
  };

  mainFunction(function(resp_message){
    if (resp_message.length != 1) {
      var i;
      speech = "";
      var displayText = "";
      for (i = 0; i < resp_message.length; i++) {
        speech = speech+resp_message[i]+'<break time="500ms"/>';
        displayText = displayText+resp_message[i]+" ";
      };
      speech = '<speak>'+speech+'</speak>';
    }
    else{
      speech ='<speak>'+resp_message+'</speak>';
      displayText = resp_message[0];
    };
    return res.json({
      fulfillmentText: speech,
      fulfillmentMessages:[
        {
          text: {
            text: [
              displayText
            ]
          }
        }
      ]
    });
  });

});


const port = process.env.PORT || 8000;
app.listen(port,()=> console.log(`Listening on port ${port}...`));

Now I updated my code according to this link by using the actions-on-google module, but without Firebase. However, I can't seem to use the http.request function inside the assistant.intent function in the way I used it before.

"use strict";

const express = require("express");
const bodyParser = require("body-parser");
const https = require('https');

const {dialogflow} = require('actions-on-google');

const assistant = dialogflow();
const app = express();

app.use(
  bodyParser.urlencoded({
    extended: true
  })
);

app.use(bodyParser.json());

assistant.intent('Default Welcome Intent', (conv) => {
  conv.ask('Welkom bij test.');
});

assistant.intent('Echo', (conv) => {
var speech = conv.query    

  var options = {
    hostname : "postman-echo.com",
    path : "/post",
    method : "POST",
    headers: {
      'Content-Type': 'application/json'
  }
  };;

  var body = JSON.stringify({message: speech});
    
  var req = https.request(options, function(res) {
      var respBody = "";
  });

  req.end(body);
  
  req.on('response', function(res){
      res.setEncoding('utf8');

      res.on('data',function(chunk){
          var temp = JSON.parse(chunk.toString());
          var resp_message = [];
          if (temp.data.length != 1) {
            var i;
            for (i = 0; i < temp.data.length; i++) {
              var resp_message_single = temp.data[i].message;
              resp_message.push(resp_message_single);
            };
            callback(resp_message)
          }
          else{
            var resp_message_single = temp.data[0].message;
            resp_message.push(resp_message_single);
            callback(resp_message)
          };
      });
  });

  mainFunction(function(resp_message){
    if (resp_message.length != 1) {
      var i;
      speech = "";
      var displayText = "";
      for (i = 0; i < resp_message.length; i++) {
        speech = speech+resp_message[i]+'<break time="500ms"/>';
        displayText = displayText+resp_message[i]+" ";
      };
      speech = '<speak>'+speech+'</speak>';
    }
    else{
      speech ='<speak>'+resp_message+'</speak>';
      displayText = resp_message[0];
    };
    conv.ask(speech);
    });

});

app.post('/echo', assistant);

const port = process.env.PORT || 8000;
app.listen(port,()=> console.log(`Listening on port ${port}...`));

Does someone know why this happens? Is the actions-on-google module preventing that?


回答1:


You have a few issues in your code that uses the actions-on-google library. One issue is that neither callback nor mainFunction() are defined - however, these errors hide a bigger problem that you'll run into.

When using the actions-on-google library (and when registering Intent Handlers using the dialogflow-fulfillment library, for that matter), you are expected to return a Promise if you're using a function that returns asynchronously, which is exactly what http.request does.

The easiest way is to switch to something like the request-promise-native library.

I haven't tested it, but the code for the Echo intent handler might look something like this:

assistant.intent('Echo', (conv) =>{
  const requestPromise = require('request-promise-native');
  const speech = conv.query;

  const options = {
    uri: "http://postman-echo.com/post",
    method: "POST",
    json: true,
    body: {
      message: speech
    }
  };

  return requestPromise( options )
    .then( body => {
      let speech = "I didn't hear anything.";
      let text   = "I didn't hear anything.";
      if (body.data && body.data.length > 0){
        speech = body.data[0].message;
        text   = body.data[0].message;
        for (let co=1; co<body.data.length; co++){
          speech += `<break time="500ms"/>${body.data[co].message}`;
          text   += ' '+body.data[co].message;
        }
      }
      speech = `<speak>${speech}</speak>`;
      return conv.ask( new SimpleResponse({
        speech: speech,
        text:   text
      }));
    });

});


来源:https://stackoverflow.com/questions/53464047/how-to-make-a-http-request-to-other-service-in-dialogflow-fulfillment-without-fi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!