Google 助手和 WorldWeatherOnline API 混淆
Google Assistant and WorldWeatherOnline API confusion
所以我刚开始为 Google 助手创建 api 代理。我遵循了 https://api.ai/docs/getting-started/basic-fulfillment-conversation 的 api.ai 文档中的所有内容,因此下方的代理会获取天气信息并 return 做出响应。这是一个有效的代码,但我想通过响应获得创意。我的目标是从响应中获取国家/地区并决定是否显示 returned 温度的摄氏度或华氏度。但是在控制台中对其进行测试后,它会继续使用摄氏度。
我还想return根据温度的友好提醒,稍后我会添加。
'use strict';
const http = require('http');
const host = 'api.worldweatheronline.com';
const wwoApiKey = '[api key]';
exports.weatherWebhook = (req, res) => {
// Get the city and date from the request
let city = req.body.result.parameters['geo-city']; // city is a required param
// Get the date for the weather forecast (if present)
let date = '';
if (req.body.result.parameters['date']) {
date = req.body.result.parameters['date'];
console.log('Date: ' + date);
}
// Call the weather API
callWeatherApi(city, date).then((output) => {
// Return the results of the weather API to API.AI
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': output, 'displayText': output }));
}).catch((error) => {
// If there is an error let the user know
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': error, 'displayText': error }));
});
};
function callWeatherApi (city, date) {
return new Promise((resolve, reject) => {
// Create the path for the HTTP request to get the weather
let path = '/premium/v1/weather.ashx?format=json&num_of_days=1' +
'&q=' + encodeURIComponent(city) + '&key=' + wwoApiKey + '&date=' + date;
console.log('API Request: ' + host + path);
// Make the HTTP request to get the weather
http.get({host: host, path: path}, (res) => {
let body = ''; // var to store the response chunks
res.on('data', (d) => { body += d; }); // store each response chunk
res.on('end', () => {
// After all the data has been received parse the JSON for desired data
let response = JSON.parse(body);
let forecast = response['data']['weather'][0];
let minTemp = forecast['mintempC'];
let maxTemp = forecast['maxtempC'];
let unit = '°C';
let location = response['data']['request'][0];
//get country
let country = location['query'].split(",")[1];
let conditions = response['data']['current_condition'][0];
let currentConditions = conditions['weatherDesc'][0]['value'];
if(country == "Liberia" || country == "Myanmar" || country == "United States of America")
{
minTemp = forecast['mintempF'];
maxTemp = forecast['maxtempF'];
unit = '°F';
}
// Create response
let output =
`Current conditions in the ${location['type']}
${location['query']} are ${currentConditions} with a projected high of
${maxTemp} ${unit} and a low of
${minTemp}${unit} on
${forecast['date']} in ${country}`;
// Resolve the promise with the output text
console.log(output);
resolve(output);
});
res.on('error', (error) => {
reject(error);
});
});
});
}
您可以使用 getUserLocale 获取用户的区域设置,而不是尝试获取用户来自哪个国家/地区他们喜欢的规模。
使用该方法,您将收到一个类似于 'en-US'
或 'en-GB'
的字符串,它们与一个国家相关联,因此您可以映射到某个温度范围。可以找到使用本地化的示例 here.
在 Google 控制台模拟器的操作中,您可以使用语言下拉菜单更改语言环境,以便您可以使用不同的语言环境测试您的应用程序。
虽然您已经用 api.ai 和 actions-on-google 标记了它,并且您的代码似乎来自 https://api.ai/docs/getting-started/basic-fulfillment-conversation#setup_weather_api,但这并不是真正的问题操作 API 本身。看起来这与您处理 WorldWeatherOnline (WWO) 结果的方式有关 API 以及您期望 Google 助手提供的输入是什么。
你有几个问题,都集中在这一行:
let country = location['query'].split(",")[1];
此行获取您在查询中提供的值。在其中,您假设了很多事情,例如:
用户指定国家(如果足够区分,WWO 可以只取一个城市)。
国家被指定为第二个字段(在谈到美国城市时,通常指定州,这将使国家成为第三个字段)。
Google 助手指定他们将国家/地区的名字大写(可能,但不能保证)。
如果国家/地区是美国,则使用确切的字符串 "United States of America" 指定,而不是像 "US" 或 "United States" 这样较短(但仍可识别)的字符串.
此外还有一个逻辑问题,即要求信息的人可能希望使用 他们 熟悉的单位,而不是 [=] 的传统单位46=]那个国家。询问西班牙天气的美国人可能仍然需要华氏温度。
无论如何 - 调试此问题的一个好方法是实际打印出 location['query']
的值,以查看各种输入的值并相应地进行调整。
我不确定是否有直接且好的方法来处理您正在尝试做的事情。一些想法:
您可以尝试在查询字符串中的任何位置查找国家/地区作为不区分大小写的子字符串,但这可能会给您带来一些误报。不过...这可能是您最简单的解决方案。
@Shuyang 的建议很好 - 但语言区域设置并不总是最好的方法,您需要使用 Google 数据操作扩展通过 API.AI.
提供
您还可以询问用户的当前位置(同样,如果您正在使用 Google 操作),然后使用地理定位器找出他们的位置。但这真的很乱。
您可以将其视为对话的一部分 - 扩展 Intent 短语以让它们指定 "in Fahrenheit" 或与其他可能的短语一起进行转换。或者在上下文中存储一些信息,如果它们构成后续短语,例如 "What is that in Fahrenheit",则提供更新、转换的信息。
(如果你真的很狡猾,你会把这个人的 userId 存储在某种数据库中,下次他们访问你时,你只需按照他们选择的单位提供它。 )
我觉得第一个最简单,最后一个最自然,但这完全取决于location['query']
的实际价值。
所以我刚开始为 Google 助手创建 api 代理。我遵循了 https://api.ai/docs/getting-started/basic-fulfillment-conversation 的 api.ai 文档中的所有内容,因此下方的代理会获取天气信息并 return 做出响应。这是一个有效的代码,但我想通过响应获得创意。我的目标是从响应中获取国家/地区并决定是否显示 returned 温度的摄氏度或华氏度。但是在控制台中对其进行测试后,它会继续使用摄氏度。 我还想return根据温度的友好提醒,稍后我会添加。
'use strict';
const http = require('http');
const host = 'api.worldweatheronline.com';
const wwoApiKey = '[api key]';
exports.weatherWebhook = (req, res) => {
// Get the city and date from the request
let city = req.body.result.parameters['geo-city']; // city is a required param
// Get the date for the weather forecast (if present)
let date = '';
if (req.body.result.parameters['date']) {
date = req.body.result.parameters['date'];
console.log('Date: ' + date);
}
// Call the weather API
callWeatherApi(city, date).then((output) => {
// Return the results of the weather API to API.AI
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': output, 'displayText': output }));
}).catch((error) => {
// If there is an error let the user know
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': error, 'displayText': error }));
});
};
function callWeatherApi (city, date) {
return new Promise((resolve, reject) => {
// Create the path for the HTTP request to get the weather
let path = '/premium/v1/weather.ashx?format=json&num_of_days=1' +
'&q=' + encodeURIComponent(city) + '&key=' + wwoApiKey + '&date=' + date;
console.log('API Request: ' + host + path);
// Make the HTTP request to get the weather
http.get({host: host, path: path}, (res) => {
let body = ''; // var to store the response chunks
res.on('data', (d) => { body += d; }); // store each response chunk
res.on('end', () => {
// After all the data has been received parse the JSON for desired data
let response = JSON.parse(body);
let forecast = response['data']['weather'][0];
let minTemp = forecast['mintempC'];
let maxTemp = forecast['maxtempC'];
let unit = '°C';
let location = response['data']['request'][0];
//get country
let country = location['query'].split(",")[1];
let conditions = response['data']['current_condition'][0];
let currentConditions = conditions['weatherDesc'][0]['value'];
if(country == "Liberia" || country == "Myanmar" || country == "United States of America")
{
minTemp = forecast['mintempF'];
maxTemp = forecast['maxtempF'];
unit = '°F';
}
// Create response
let output =
`Current conditions in the ${location['type']}
${location['query']} are ${currentConditions} with a projected high of
${maxTemp} ${unit} and a low of
${minTemp}${unit} on
${forecast['date']} in ${country}`;
// Resolve the promise with the output text
console.log(output);
resolve(output);
});
res.on('error', (error) => {
reject(error);
});
});
});
}
您可以使用 getUserLocale 获取用户的区域设置,而不是尝试获取用户来自哪个国家/地区他们喜欢的规模。
使用该方法,您将收到一个类似于 'en-US'
或 'en-GB'
的字符串,它们与一个国家相关联,因此您可以映射到某个温度范围。可以找到使用本地化的示例 here.
在 Google 控制台模拟器的操作中,您可以使用语言下拉菜单更改语言环境,以便您可以使用不同的语言环境测试您的应用程序。
虽然您已经用 api.ai 和 actions-on-google 标记了它,并且您的代码似乎来自 https://api.ai/docs/getting-started/basic-fulfillment-conversation#setup_weather_api,但这并不是真正的问题操作 API 本身。看起来这与您处理 WorldWeatherOnline (WWO) 结果的方式有关 API 以及您期望 Google 助手提供的输入是什么。
你有几个问题,都集中在这一行:
let country = location['query'].split(",")[1];
此行获取您在查询中提供的值。在其中,您假设了很多事情,例如:
用户指定国家(如果足够区分,WWO 可以只取一个城市)。
国家被指定为第二个字段(在谈到美国城市时,通常指定州,这将使国家成为第三个字段)。
Google 助手指定他们将国家/地区的名字大写(可能,但不能保证)。
如果国家/地区是美国,则使用确切的字符串 "United States of America" 指定,而不是像 "US" 或 "United States" 这样较短(但仍可识别)的字符串.
此外还有一个逻辑问题,即要求信息的人可能希望使用 他们 熟悉的单位,而不是 [=] 的传统单位46=]那个国家。询问西班牙天气的美国人可能仍然需要华氏温度。
无论如何 - 调试此问题的一个好方法是实际打印出 location['query']
的值,以查看各种输入的值并相应地进行调整。
我不确定是否有直接且好的方法来处理您正在尝试做的事情。一些想法:
您可以尝试在查询字符串中的任何位置查找国家/地区作为不区分大小写的子字符串,但这可能会给您带来一些误报。不过...这可能是您最简单的解决方案。
@Shuyang 的建议很好 - 但语言区域设置并不总是最好的方法,您需要使用 Google 数据操作扩展通过 API.AI.
提供
您还可以询问用户的当前位置(同样,如果您正在使用 Google 操作),然后使用地理定位器找出他们的位置。但这真的很乱。
您可以将其视为对话的一部分 - 扩展 Intent 短语以让它们指定 "in Fahrenheit" 或与其他可能的短语一起进行转换。或者在上下文中存储一些信息,如果它们构成后续短语,例如 "What is that in Fahrenheit",则提供更新、转换的信息。
(如果你真的很狡猾,你会把这个人的 userId 存储在某种数据库中,下次他们访问你时,你只需按照他们选择的单位提供它。 )
我觉得第一个最简单,最后一个最自然,但这完全取决于location['query']
的实际价值。