Actions on google 运行nodejs的webhook的正确响应方式是什么?
正在尝试实现运行nodejs的web钩子(使用V2 dialogflow)。收到的响应“必须设置格式错误的响应‘最终响应’。”。下面是代码。在POST(app.POST)末尾,代码块预期conv.close将发送SimpleResponse。但事实并非如此。需要帮助了解出现此错误的原因以及解决此错误的可能方向 谢谢Actions on google 运行nodejs的webhook的正确响应方式是什么?,actions-on-google,Actions On Google,正在尝试实现运行nodejs的web钩子(使用V2 dialogflow)。收到的响应“必须设置格式错误的响应‘最终响应’。”。下面是代码。在POST(app.POST)末尾,代码块预期conv.close将发送SimpleResponse。但事实并非如此。需要帮助了解出现此错误的原因以及解决此错误的可能方向 谢谢 const express = require('express'); const { dialogflow, Image, SimpleResponse, } = re
const express = require('express');
const {
dialogflow,
Image,
SimpleResponse,
} = require('actions-on-google')
const bodyParser = require('body-parser');
const request = require('request');
const https = require("https");
const app = express();
const Map = require('es6-map');
// Pretty JSON output for logs
const prettyjson = require('prettyjson');
const toSentence = require('underscore.string/toSentence');
app.use(bodyParser.json({type: 'application/json'}));
// http://expressjs.com/en/starter/static-files.html
app.use(express.static('public'));
// http://expressjs.com/en/starter/basic-routing.html
app.get("/", function (request, response) {
console.log("Received GET request..!!");
//response.sendFile(__dirname + '/views/index.html');
response.end("Response from my server..!!");
});
// Handle webhook requests
app.post('/', function(req, res, next) {
console.log("Received POST request..!!");
// Log the request headers and body, to aide in debugging. You'll be able to view the
// webhook requests coming from API.AI by clicking the Logs button the sidebar.
console.log('======Req HEADERS================================================');
logObject('Request headers: ', req.headers);
console.log('======Req BODY================================================');
logObject('Request body: ', req.body);
console.log('======Req END================================================');
// Instantiate a new API.AI assistant object.
const assistant = dialogflow({request: req, response: res});
// Declare constants for your action and parameter names
//const PRICE_ACTION = 'price'; // The action name from the API.AI intent
const PRICE_ACTION = 'revenue'; // The action name from the API.AI intent
var price = 0.0
// Create functions to handle intents here
function getPrice(assistant) {
console.log('** Handling action: ' + PRICE_ACTION);
let requestURL = 'https://blockchain.info/q/24hrprice';
request(requestURL, function(error, response) {
if(error) {
console.log("got an error: " + error);
next(error);
} else {
price = response.body;
logObject('the current bitcoin price: ' , price);
// Respond to the user with the current temperature.
//assistant.tell("The demo price is " + price);
}
});
}
getPrice(assistant);
var reponseText = 'The demo price is ' + price;
// Leave conversation with SimpleResponse
assistant.intent(PRICE_ACTION, conv => {
conv.close(new SimpleResponse({
speech: responseText,
displayText: responseText,
}));
});
}); //End of app.post
// Handle errors.
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(500).send('Oppss... could not check the price');
})
// Pretty print objects for logging.
function logObject(message, object, options) {
console.log(message);
console.log(prettyjson.render(object, options));
}
// Listen for requests.
let server = app.listen(process.env.PORT || 3000, function () {
console.log('Your app is listening on ' + JSON.stringify(server.address()));
});
通常,必须设置“final\u response”(最终响应)
错误是因为您没有返回任何内容。您的代码中有很多内容,虽然您走在正确的轨道上,但代码中有一些东西可能会导致此错误
首先,在代码中,您似乎对如何发送响应感到困惑。您既有对conv.close()
的调用,也有注释掉的assistant.tell()
。conv.close()
或conv.ask()
方法是使用此版本库发送回复的方法。早期版本使用了tell()
方法,不再支持该方法
接下来,您的代码看起来好像只在调用路由函数时设置助手对象。虽然这是可以做到的,但这不是通常的做法。通常,作为程序初始化的一部分,您将创建助手对象并设置意图处理程序(使用assistant.Intent()
)。这大致相当于在请求到来之前设置express应用程序及其路由
设置助手并将其挂接到路线的部分可能如下所示:
const assistant = dialogflow();
app.post('/', assistant);
const rp = require('request-promise-native');
function getPrice(){
return rp.get(url)
.then( body => {
// In this case, the body is the value we want, so we'll just return it.
// But normally we have to get some part of the body returned
return body;
});
}
assistant.intent(PRICE_ACTION, conv => {
return getPrice()
.then( price => {
let msg = `The price is ${price}`;
conv.close( new SimpleResponse({
speech: msg,
displayText: msg
});
});
});
如果您真的想首先检查请求和响应对象,您可以这样做
const assistant = dialogflow();
app.post('/', function( req, res ){
console.log(JSON.stringify(req.body,null,1));
assistant( req, res );
});
与此相关的是,您试图在路由处理程序中执行代码,然后尝试调用意图处理程序。同样,这是可能的,但不是使用库的建议方法。(我还没有试着调试您的代码,看看您在如何做时是否有问题,看看您做得是否有效。)更典型的做法是从Intent处理程序内部调用getPrice()
,而不是尝试从route处理程序内部调用它
但这导致了另一个问题。getPrice()
函数调用request()
,这是一个异步调用。异步调用是导致空响应的最大问题之一。如果使用异步调用,则必须返回承诺。在request()
中使用承诺最简单的方法是使用包
因此,这段代码可能看起来(非常粗略)如下:
const assistant = dialogflow();
app.post('/', assistant);
const rp = require('request-promise-native');
function getPrice(){
return rp.get(url)
.then( body => {
// In this case, the body is the value we want, so we'll just return it.
// But normally we have to get some part of the body returned
return body;
});
}
assistant.intent(PRICE_ACTION, conv => {
return getPrice()
.then( price => {
let msg = `The price is ${price}`;
conv.close( new SimpleResponse({
speech: msg,
displayText: msg
});
});
});
关于getPrice()
和intent处理程序,需要注意的重要一点是它们都返回一个承诺
最后,代码中有一些奇怪的方面。行,例如
res.status(500).send('opps…无法检查价格')代码>可能不会做你认为他们会做的事情。例如,它不会发送要说的信息。相反,助手只需关闭连接,然后说出现了问题。非常感谢@capture。以下是基于上述意见的V2工作解决方案。在nodejs webhook(没有firebase)上也验证了这一点。代码的V1版本是从中引用的
快乐的编码
// init project pkgs
const express = require('express');
const rp = require('request-promise-native');
const {
dialogflow,
Image,
SimpleResponse,
} = require('actions-on-google')
const bodyParser = require('body-parser');
const request = require('request');
const app = express().use(bodyParser.json());
// Instantiate a new API.AI assistant object.
const assistant = dialogflow();
// Handle webhook requests
app.post('/', function(req, res, next) {
console.log("Received POST request..!!");
console.log('======Req HEADERS============================================');
console.log('Request headers: ', req.headers);
console.log('======Req BODY===============================================');
console.log('Request body: ', req.body);
console.log('======Req END================================================');
assistant(req, res);
});
// Declare constants for your action and parameter names
const PRICE_ACTION = 'revenue'; // The action name from the API.AI intent
var price = 0.0
// Invoke http request to obtain blockchain price
function getPrice(){
console.log('getPrice is invoked');
var url = 'https://blockchain.info/q/24hrprice';
return rp.get(url)
.then( body => {
// In this case, the body is the value we want, so we'll just return it.
// But normally we have to get some part of the body returned
console.log('The demo price is ' + body);
return body;
});
}
// Handle AoG assistant intent
assistant.intent(PRICE_ACTION, conv => {
console.log('intent is triggered');
return getPrice()
.then(price => {
let msg = 'The demo price is ' + price;
conv.close( new SimpleResponse({
speech: msg,
}));
});
});
// Listen for requests.
let server = app.listen(process.env.PORT || 3000, function () {
console.log('Your app is listening on ' + JSON.stringify(server.address()));
});
通过显式添加以下内容解决了问题:var resp_obj={“payload”:{“google”:{“expectUserResponse”:false,“richResponse”:{“items”:[{“simpleResponse”:{“textToSpeech”:responseText}}}}} }; res.writeHead(200,{“内容类型”:“application/json”});res.end(JSON.stringify(resp_obj));如果有更好的方法,请建议。谢谢,非常感谢囚犯。非常有用。