The google action simulator can't reach my web server - dialogflow-es

I try to test my google assistant application but the console.action simulator can't reach my web server while the "dialogflow simulator" can (Dialogflow simulator screenshot). I don't get any request from it in my ngrok console.
When I write in the simulator "Talk to my test app", I get the following error:
We're sorry, but something went wrong. Please try again.
.
{
"response": "We're sorry, but something went wrong. Please try again.",
"expectUserResponse": false,
"conversationToken": "",
"audioResponse": "",
"ssmlMarkList": [],
"visualResponse": {
"visualElementsList": [
{
"displayText": {
"content": "Sorry, this action is not available in simulation"
}
}
],
"suggestionsList": [],
"agentLogoUrl": ""
},
"clientError": 8,
"is3pResponse": false,
"clientOperationList": [],
"projectName": "",
"renderedHtml": "",
"previewStartTimeMicros": "",
"isEmptyResponse": false,
"agentName": "",
"servingModelOutdated": false
}
All the solutions I tried:
I enabled web & App activity on my personnal account (App activity screenshot).
I enabled logs and applied the query "resource.type="global"" but no log appears (except those resulting from the tests carried out with dialogflow).
I have manually modified the webhook address of the simulator.
Webhook simulator screenshot
I deleted my project several times and recreated it.
I tried to invoke the wizard on my phone.
I tried ngrok and localtunnel
On dialogflow, I went to settings => Share and added a new user as Developper (a child account of my main google account). I then went to the IAM console and gave him the following rights: "Dialogflow API Client", "Reader". I accessed the simulator with this account via another browser but the error persists. (Source)
I activated/desactivated the webhook for the intent "Default Welcome Intent".
I changed the language and the localization of the simulator by those which I had informed during the creation of the project (Simulator location screenshot).
Here is a extract of my code:
const {
dialogflow,
actionssdk,
Image,
Table,
Carousel,
List,
} = require('actions-on-google');
const express = require('express');
const bodyParser = require('body-parser');
const app = dialogflow({
debug: false
});
app.intent('Default Welcome Intent', (conv, params) => {
conv.ask(`Salut mec ca va ?`);
});
app.catch((conv, error) => {
console.error(error);
conv.ask(`J'ai rencontré un problème, pouvez-vous répéter ?`);
});
app.fallback((conv) => {
conv.ask(`Je n'ai pas compris. Pouvez-vous répéter ?`);
});
express().use(bodyParser.json(), app).listen(3000);

This is a dedicated page for actions that are stuck in review, but it also offers some other support options.
https://support.google.com/actions-console/contact/support

Related

Cannot insert a comment on a youtube video using the Youtube Data API

I am using the Youtube Data API to insert a video.
The I use the API to insert a "commentThread" to the video, as described here in the doc. Here is my code:
import { google } from "googleapis";
const googleApiClient = new google.auth.OAuth2(
GOOGLE_CLIENT_SECRET.web.client_id,
GOOGLE_CLIENT_SECRET.web.client_secret,
GOOGLE_CLIENT_SECRET.web.redirect_uris[0]
);
googleApiClient.credentials = tokens;
google.options({ auth: googleApiClient });
const apiYoutube = google.youtube({ version: "v3" });
await apiYoutube.commentThreads.insert({
part: ["snippet"],
requestBody: {
snippet: {
videoId,
topLevelComment: {
snippet: {
textOriginal: "Hello world!",
},
},
},
},
});
Depending on the video visibility, the response differs:
if visibility is "private", I get a 403 error:
{
message: 'The comment thread could not be created due to insufficient permissions. The request might not be properly authorized.',
domain: 'youtube.commentThread',
reason: 'forbidden',
location: 'body',
locationType: 'other'
}
I am positive that my access token (acquired through an oauth2 process) has the correct scope: "https://www.googleapis.com/auth/youtube.force-ssl"
if visibility is "public" or "unlisted", I get a 400 error:
{
message: 'This action is not available for the item.',
domain: 'youtube.mfk',
reason: 'mfkWrite'
}
In the youtube console, in Settings > Upload defaults > Avanced settings > comments, it is set to "Hold potentially inappropriate comments for review". I have also tried "Allow all comments".
How can I fix this issue and publish comments to my video?
I am aware of this similar question and tried the various suggestions but it still does not work and the API may have evolved.

Test suite for smart home doesn't pass with one action, but it does with another one with the exact same code

we've developed a smart home action for Google Assistant and our "staging action" passed the test suite for smart home. Now that we wanted to get the "production action" certified, the test suite didn't pass, not a single command worked. The devices' states changed correctly, but the test suite returned the following error: AssertionError: Expected state to include: {"on":true}, actual state: {}: expected false to be true
We've had the problem before with the "staging action" and identified it to be a HomeGraph Sync problem. We fixed it and afterwards it worked. The "production action's" code is the exact same as the "staging action's" and the settings are also the same. So we have no idea what we could do to make the test suite pass. Does anyone have an idea of what the problem might be?
Here is an excerpt of our code:
const { smarthome } = require('actions-on-google');
// creating app in constructor
this._app = smarthome({ jwt, debug: this._options.debug || false });
// code-snipped sending state to HomeGraph after creating the state object from our device states
console.info('Report state:');
console.info(inspect(state, {depth: null, showHidden: false}));
this._app.reportState(state)
.then(res => console.info('report state succeeded', res))
.catch(err => console.error('report state failed', err));
And here is the corresponding log:
Report state:
{
requestId: 'c82c0c20-a10d-4ded-a456-319109188501',
agentUserId: '730f1842168ade4dcf9be3e40ea279e7ac4e6f21c002c09909f9d9a0341d2214',
payload: {
devices: {
states: {
'500dc011398fd3c191efdfa8e13a1062f7ef4d1c': { on: true, online: true }
}
}
}
}
report state succeeded {
"requestId": "c82c0c20-a10d-4ded-a456-319109188501"
}
In case of an error we expect something like:
404: agentUserId unknown or HomeGraph not enabled
401: access rights misconfigured
or any other error
but it succeeds.
EDITED:
We adjusted our code by reading the state from HomeGraph directly after sending it to HomeGraph in order to see whether HomeGraph gets anything from us at all:
const auth = new google.auth.GoogleAuth({
credentials: jwt,
scopes: ['https://www.googleapis.com/auth/homegraph']
});
this._hg = google.homegraph({
version: 'v1',
auth: auth,
});
this._app = smarthome({ jwt, debug: this._options.debug || false });
this._app.reportState(state).then(async res => {
const request = {
requestBody: {
agentUserId: state.agentUserId,
inputs: [{
payload: {
devices: Object.keys(state.payload.devices.states).map(id => ({id}))
}
}]
}
};
console.info(require('util').inspect(request, {depth: null}));
const readStates = await this._hg.devices.query(request);
console.info('########## STATES in HOMEGRAPH #######################');
console.info(readStates.data);
return res;
})
.catch(err => console.error('report state failed', err));
The state is empty.
We also implemented a simple node.js app to read all device states via HomeGraph API. All device states are empty at any time.
The main question is: Why does calling this._app.reportState(state) never run into catch handler? There must be something wrong with our sending the state to HomeGraph, but we do not get any error back...?
Thanks! The problem has sorted itself out somehow. Maybe Google had a bug, but without doing anything on our part the tests pass now.
If you're getting {} as the actual state value, then it seems like the Test Suite is unable to read data from the Home Graph. There are two likely reasons for this.
In your production project, your test account has a different agentUserId
Your production project will have a different service account key than your staging project. You may be uploading the wrong key, which causes the Home Graph API calls in the test suite to be unsuccessful.

App isn't responding right now. MalformedResponse - Could not find a RichResponse or SystemIntent in the platform response

I'm trying to get through the codelabs tutorial for Google Actions and running into some trouble. I'm on "Build Actions for the Assistant (Level 2)".
When I try to test the action in the simulator, I get "My test app isn't responding right now. Try again soon."
There is nothing in the request or response tabs. Here is the debug tab output:
{
"response": "My test app isn't responding right now. Try again soon.",
"expectUserResponse": false,
"conversationToken": "EvwCS2o5Wk...",
"audioResponse": "//NExAASeH...",
"ssmlMarkList": [],
"debugInfo": {
"sharedDebugInfoList": []
},
"visualResponse": {
"visualElementsList": [
{
"displayText": {
"content": "My test app isn't responding right now. Try again soon."
}
}
],
"suggestionsList": [],
"agentLogoUrl": ""
},
"clientError": 0,
"is3pResponse": true,
"clientOperationList": [],
"projectName": ""
}
My code:
'use strict';
// Import the Dialogflow module from the Actions on Google client library.
const {
dialogflow,
Permission,
Suggestions,
} = require('actions-on-google');
// Import the firebase-functions package for deployment.
const functions = require('firebase-functions');
// Instantiate the Dialogflow client.
const app = dialogflow({debug: true});
// Handle the Dialogflow intent named 'favorite color'.
// The intent collects a parameter named 'color'.
app.intent('favorite color', (conv, {color}) => {
const luckyNumber = color.length;
// Respond with the user's lucky number and end the conversation.
if (conv.data.userName) {
conv.close(`${conv.data.userName}, your lucky number is ${luckyNumber}.`);
} else {
conv.close(`Your lucky number is ${luckyNumber}.`);
};
});
app.intent('Default Welcome Intent', (conv) => {
const options = {
context: 'Hi there, to get to know you better',
permissions: ['NAME'],
};
conv.ask(new Permission(options));
});
// Handle the Dialogflow intent named 'actions_intent_PERMISSION'. If user
// agreed to PERMISSION prompt, then boolean value 'permissionGranted' is true.
app.intent('ask permission', (conv, params, permissionGranted) => {
// If they didn't give me permission to use their name...
const options = ['Blue', 'Red', 'Green'];
if (!permissionGranted) {
conv.ask("Ok, no worries. What\'s your favorite color?");
conv.ask(new Suggestions(options));
} else {
// Otherwise, they gave me permission to use it
conv.data.userName = conv.user.name.display;
conv.ask(`Thanks, ${conv.data.userName}. What's your favorite color?`);
conv.ask(new Suggestions(options));
};
});
// Set the DialogflowApp object to handle the HTTPS POST request.
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
There is also nothing in the "Error" tab. I've tried hunting down the meaning of clientError: 0 to see if that helps to no avail. I've also tried hunting down the MalformedResponse error, but I'm not getting a lot of helpful information.
I've tried all kinds of moving code around or re-writing it and nothing changes the error message. I have no idea why it's breaking.
The logs here (https://console.cloud.google.com) for this action say:
MalformedResponse: ErrorId: a5421d80-def5-42ef-ba55-8ac95a879e14. Failed to parse Dialogflow response into AppResponse because of invalid platform response. : Could not find a RichResponse or SystemIntent in the platform response for agentId: 6edfe023-05da-4726-9ee7-6469f0a5fb3d and intentId: 8ad48133-dd71-496c-b5af-d4ec19e88309
I've tried hunting that down and can't find much helpful information about it.
Another thing I have noticed is the logs for this function at https://console.firebase.google.com don't seem to be updating. The last log I have is on 6/2, when the function first broke. I have no idea why it won't update. If I run firebase functions:log, I'll have more recent entries that look like:
2019-06-16T22:20:20.246Z I :
2019-06-16T22:20:21.895Z N dialogflowFirebaseFulfillment:
2019-06-16T22:21:01.674Z N dialogflowFirebaseFulfillment:
2019-06-16T22:27:45.629Z I :
2019-06-16T22:27:47.249Z N dialogflowFirebaseFulfillment:
2019-06-16T22:28:15.351Z N dialogflowFirebaseFulfillment:
2019-06-16T22:59:06.793Z I :
2019-06-16T22:59:08.488Z N dialogflowFirebaseFulfillment:
2019-06-16T22:59:49Z N dialogflowFirebaseFulfillment:
At one point, those logs said "Undefined" next to dialogflowFirebaseFulfillment:, but something changed and I don't know what.
Any help would be greatly appreciated as I've exhausted every option I can think of at this point.
Okay, I finally figured it out. I'm not sure what changed, but I think it's the migration from V1 to V2 in Dialog Flow (so the tutorial wasn't really correct) and I was looking in the wrong github docs for help.
This line...
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
Needed to be changed to...
exports.fulfillment = functions.https.onRequest(app);
I had a feeling it had to do with my deployment to Firebase, but what put me on the right track was checking out this page: https://github.com/actions-on-google/actions-on-google-nodejs
Specifically, the section talking about frameworks and exporting to the appropriate one.
Hope this helps anyone else in a similar situation :)

Google Cloud HTTP function by webhook: Request body is missing data

Im integrating the Zoom API with my Firebase app, and to do so I'm relying on Zooms pre-made webhooks to run an HTTP function on my Firebase for various events like "meeting started" and "meeting ended". Zoom API reference: https://marketplace.zoom.us/docs/guides/webhooks
This is the Google Cloud function that the Zoom API is calling:
exports.zoomTestA = functions.https.onCall((req, res) => {
console.log(req);
let data = req.body;
var xmlData = data.toString();
console.log(xmlData);
});
Here is the payload sent by Zoom:
{
"event": "meeting.ended",
"payload": {
"account_id": "LTf-KjgUTR2df-knT8BVEw",
"object": {
"duration": 0,
"start_time": "2019-05-07T14:02:51Z",
"timezone": "",
"topic": "Alexander Zoom Meeting",
"id": "864370042",
"type": 1,
"uuid": "2h/SWVrrQMu7fcbpLUly3g==",
"host_id": "Ty6ykNolSU2k1N4oc0NRcQ"
}
}
This causes this error to appear in my Google Cloud console:
Request body is missing data. { event: 'meeting.ended',
payload:
{ account_id: 'LTf-KjgUTR2df-knT8BVEw',
object:
{ duration: 0,
start_time: '2019-04-30T14:23:44Z',
timezone: '',
topic: 'Alexander\'s Zoom Meeting',
id: '837578313',
type: 1,
uuid: 'WotbHO3RRpSviETStKEGYA==',
host_id: 'Ty6ykNolSU2k1N4oc0NRcQ' } } }
The request body that Zoom sends is not wrapped in in a "data: {}" tag as required by Google Cloud functions. I've found solutions to this problem if you can control the payload here: Dart json.encode is not encoding as needed by Firebase Function .
My problem is that I am unable to alter the request that the Zoom API sends. Is there any way I can still accept the request in my Google Cloud function? Or is there any way to alter the format of the request sent by Zoom? I'm unable to find references for either.
One potential solution would be to set up another server that receives the request by Zoom, format it to Google Cloud functions specifications, and then pass it on to my Google Cloud function. I would however like to avoid stepping out of the Google Cloud eco-system.
Is this problem solvable on the Google Cloud platform?
So I figured it out. In Firebase / Google Cloud functions you can either make HTTP-functions with
functions.https.onCall((req, res) => {
var data = req.body;
and
functions.https.onRequest((req, res) => {
var data = req.body;
The difference seems to be that onCall is made for being used within the Firebase/ Google Cloud functions environment. However if you wan external functions you need to use onRequest as this does not require specific formatting of the payload.
Using onRequest instead solved all my problems.

Slack Interactive Messages: No POST response from Slack

I'm constructing and sending the message attachment:
var zz = {
"text": "Would you like to play a game??",
"attachments": [
{
"text": "Choose a game to play",
"fallback": "You are unable to choose a game",
"callback_id": "wopr_game",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "chess",
"text": "Chess",
"type": "button",
"value": "chess"
}
]
}
]
}
web.chat.postMessage(message.source.channel, '', zz);
The message with buttons displays fine on Slack, but when I tap a button there's no POST response from Slack to my local ngrok or express route:
app.post('/slackaction', function(req, res)
While other messages are posting fine to this route.
I'm seeing this error from Slack after I tap a button:
"Oh no, something went wrong. Please try that again"
Slack Interactive Messages request_url set as:
https://xxx.ngrok.io/slackaction
Thanks to comments from Taylor Singletary for pointing me in the right direction.
The test tokens or a bot token for Custom Integrations can post Interactive Messages but you need an App to handle them.
To fix it you need to add a bot to your app here: https://api.slack.com/apps
and then get the access token for that bot.
You can use the Slack button generator here: https://api.slack.com/docs/slack-button# to get the OAuth URL and paste it on a browser.
Then from your app handle the OAuth flow, store the access token and use that with chat.postMessage.
Then you should receive the POST request when clicking on the message buttons.

Resources