问题
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