Google Action not deploying - actions-on-google

I'm trying to get a simple audio stream playing in a Google Action cloud function. It won't deploy as it says there are errors in the code, but it's not saying where. Here's my code (note the alternatives in *** comments - confusing as I'm not sure which I should be using, having seen both!
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
const { MediaObject, SimpleResponse } = require('actions-on-google');
const app = actionssdk() // *** or 'const app = conversation()' ?
app.handle("playStream", conv => { // *** or 'app.intent(...' ?
conv.ask(new SimpleResponse("Playing stream"));
conv.ask(new MediaObject({
name: 'My stream',
url: 'https://stream.redacted.url',
description: 'The stream',
icon: new Image({
url: 'https://image.redacted.url', alt: 'Media icon',
}),
}));
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

You seem to be using a mix of actions-on-google and #assistant/conversation libraries. You should only be using one or the other, depending on what platform you are using.
If you are using the original Actions SDK, you should use actions-on-google. If you are using the new Actions SDK or Actions Builder, you should use #assistant/conversation.
The distinctions are different but will result in problems. actionssdk has an intent method but not a handle method, and vice versa for conversation. This can result in a syntax error. Also make sure you've imported everything, including Image.
const functions = require('firebase-functions')
const {
conversation,
Media,
Image,
} = require('#assistant/conversation')
const app = conversation()
app.handle("playStream", conv => {
conv.add("Playing stream");
conv.add(new Media({
mediaObjects: [{
name: 'Media name',
description: 'Media description',
url: 'https://actions.google.com/sounds/v1/cartoon/cartoon_boing.ogg',
image: {
large: new Image({
url: 'https://image.redacted.url',
alt: 'Media icon',
}),
}
}],
mediaType: 'AUDIO',
optionalMediaControls: ['PAUSED', 'STOPPED']
}));
})
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app)
If this still doesn't work, you should add what errors you're seeing in trying to deploy.

Related

Android Enterprises Device Enrollment Stuck with NodeJs Generated QR Code with Service Account Authentication

As mentioned in the google documents i have tested the following process
URL to quick start: https://colab.research.google.com/github/google/android-management-api-samples/blob/master/notebooks/quickstart.ipynb#scrollTo=pjHfDSb8BoBP
Create Enterprise
Create Policy
Enroll the device
Then I have used the NODEJS API of Android Enterprises to develop the server based solution, which is working fine as per the documentation for all the functions such as get, create, delete the policy, devices, enterprises.
The issue i am facing is with the QR code generated from NODE application, when i scan the QR code generated from NODEJS application, the device got stuck at system update.
Following is my Policy update function
router.post('/update/:id', async function(req, res) {
const {title,policy_body,update_mask,enroll_url} = req.body;
// here we are callng the android managment API to and then the response we will update to database
const amApiBody = {
name: policy_body.name,
updateMask:update_mask,
requestBody:policy_body
}
const policy_update_response = await amApi.updatePolicy(amApiBody);
const p = await policyModel.update(req.params.id,title,policy_update_response,enroll_url);
res.json(p)
});
AmAPI file
this.updatePolicy = async function (body)
{
const auth = new google.auth.GoogleAuth({
scopes: ['https://www.googleapis.com/auth/androidmanagement'],
});
const authClient = await auth.getClient();
google.options({auth: authClient});
// Get the list of available policies
const res = await androidmanagement.enterprises.policies.patch(body);
console.log('requestFinalBody=',body);
return res.data;
}
Following is my policy data obtained by running above function
policy_create_response= {
name: 'enterprises/LC019rjnor/policies/policy1',
version: '14',
applications: [
{
packageName: 'com.google.samples.apps.iosched',
installType: 'FORCE_INSTALLED',
autoUpdateMode: 'AUTO_UPDATE_HIGH_PRIORITY'
},
{
packageName: 'com.dekaisheng.courier',
installType: 'FORCE_INSTALLED',
autoUpdateMode: 'AUTO_UPDATE_HIGH_PRIORITY'
}
],
keyguardDisabledFeatures: [ 'KEYGUARD_DISABLED_FEATURE_UNSPECIFIED' ],
defaultPermissionPolicy: 'GRANT',
uninstallAppsDisabled: true,
keyguardDisabled: true,
tetheringConfigDisabled: true,
dataRoamingDisabled: true,
networkEscapeHatchEnabled: true,
bluetoothDisabled: true,
debuggingFeaturesAllowed: true,
funDisabled: true,
kioskCustomLauncherEnabled: true
}
Note i have exported the variable to the terminal as follows before running the app, the auth.json is the service account credential file.
export GOOGLE_APPLICATION_CREDENTIALS="/Users/Mac/Projects/wajid/mdm/server/env/auth.json"
Thanks for the help in advance
I figured out that in nodeJS API I was passing wrong property name of Policy value in the request body.
Code before fix
parent: this.getParent(policyName),
requestBody:{
“name”: “my_policy"
}
Code after fix
parent: this.getParent(policyName),
requestBody:{
"policyName”: “my_policy"
}

media status is not giving any response actions on google/ Actions builder

As you can see I am playing the audio with MediaObject. Audio is playing but I am getting 'undefined' in mediaStatus
`app.handle('Default_Welcome_Intent', (conv) => {
conv.add('This is a media response');
conv.add(new Media({
mediaObjects: [
{
name: 'Media name',
description: 'Media description',
url: 'https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3',
image: {
large: ASSISTANT_LOGO_IMAGE,
}
}
],
mediaType: 'AUDIO',
optionalMediaControls: ['PAUSED', 'STOPPED'],
startOffset: '0s'
}));
const mediaStatus = conv.intent.params.MEDIA_STATUS.resolved;
return console.log(mediaStatus)
});`
By the time you're making the call, your intent handler has not yet completed. As such, the media hasn't begun playing by the time you're querying the media status. It's intentional that the status is unresolved by this point.
The media status will change later in the conversational flow. You'll want to read the documentation on receiving media status to your webhook at a later point in order to get the status and current media progress.

React Testing Library for Actions in redux

I am new to React Testing Library and have issue with actions.
Can anyone please guide me
I have tried below code and its giving error Received: [Function anonymous]
export const openText = () => (dispatch: Dispatch) => {
dispatch({
type: actionTypes.Text,
payload: true
});
};
Test Case
it('open text() => {
const expectedAction = {
type: actionTypes.OPEN_Text,
payload:'value
};
const action = actions.openText('value);
expect(action).toEqual(expectedAction);
});
Error: It says Received: [Function anonymous]
React Testing Library, as the name implies, is used for testing React components. You do not need it in this case.
You seem to be trying to test a Redux action creator. I suggest you follow the async action creators section from the Redux docs.
Your test currently fails because you are expecting to receive an object but your action creator returns a function.

Perculiar error when trying to make request to local GQL endpoint

I'm attempting to set up a android application in react-native and it's calling a local API.
Ideally here I'd like the see the API request actually succeed or at least return me a formatted GraphQL exception that should be produced in my back-end.
My GraphQL api is running on localhost:3000
I've already tried the generic solutions for my any question that I've stumbled across
Set up an android emulator HTTP proxy to 10.0.2.2:3000
I've set up the ApolloClient like so
const client = new ApolloClient({
link: new HttpLink({
uri: Platform.select({
android: 'http://"my machine ip here" / ipv4 /graphql'
})
}),
cache: new InMemoryCache(),
});
I've also tried
const client = new ApolloClient({
link: new HttpLink({
uri: Platform.select({
android: 'http://10.0.2.2:3000/graphql'
})
}),
cache: new InMemoryCache(),
});
The API request is made here:
const [login, {data, loading, error}] = useMutation(LoginUserMutation);
return <LoginWrapper>
<Formik
initialValues={{email: '', password: ''}}
onSubmit={async ({email, password}) => {
const user = await login({variables: {email, password}});
}}
>
{({
values,
handleChange,
errors,
setFieldTouched,
touched,
isValid,
handleSubmit
}) => <>
<Input
value={values.email}
onChangeText={handleChange('email')}
onBlur={() => setFieldTouched('email')}
placeholder='E-mail'
/>
<Input
value={values.password}
onChangeText={handleChange('password')}
placeholder='Password'
onBlur={() => setFieldTouched('password')}
secureTextEntry={true}
/>
<Button
onClick={handleSubmit}
text='Sign In'
/>
</>}
</Formik>
</LoginWrapper>
};
The graphql mutation can be seen here
export const LoginUserMutation =
gql(
mutation('loginUser',
params(
{
$args: 'LoginUserInput!'
},
{
updateUser: params({args: '$args'},
{
email: types.string,
}
),
})
)
);
Image of error can be found here -
https://imgur.com/a/6odLPnU
Partial stack trace here -
Possible Unhandled Promise Rejection (id: 0):
Error: Network error: Response not successful: Received status code 400
ApolloError#blob:http://localhost:8081/86efb950-3eff-404f-bc63-41535a310e3a:92518:28
error#blob:http://localhost:8081/86efb950-3eff-404f-bc63-41535a310e3a:93755:30
notifySubscription#blob:http://localhost:8081/86efb950-3eff-404f-bc63-41535a310e3a:141965:20
onNotify#blob:http://localhost:8081/86efb950-3eff-404f-bc63-41535a310e3a:142004:23
So I've solved the problem.
The mutation should have been
export const LoginUserMutation = gql(
mutation('login',
params({$args: 'LoginUserInput!'}, {
login: params({args: '$args'}, {
token: types.string,
}),
})
)
);
The calling of the mutation should have been
const [login, {data, loading, error}] = useMutation(LoginUserMutation);
await login({variables: {args: {email, password}}})

How to return List in Dialogflow webhooks APIV2?

I have seen most of the examples related to how to return rich content via webhooks involving just basic response and Card.
https://github.com/dialogflow/fulfillment-webhook-nodejs/blob/master/functions/index.js
What's the structure needed in dialogflow webhook V2 response to return either List or Carousel?
If you want to incorporate carousels and lists with Dialogflow, you'll need to import the actions-on-google module, as not all rich responses are supported by Dialogflow alone. You can see on the Actions on Google Rich Responses reference docs. Also there's a Fulfillment-Actions on Google sample
const { WebhookClient } = require('dialogflow-fulfillment');
const { Carousel } = require('actions-on-google');
conv.ask(new Carousel({
items: {
// Add the first item to the carousel
[SELECTION_KEY_ONE]: {
synonyms: [
'synonym of title 1',
'synonym of title 2',
'synonym of title 3',
],
title: 'Title of First Carousel Item',
description: 'This is a description of a carousel item.',
image: new Image({
url: IMG_URL_AOG,
alt: 'Image alternate text',
}),
},
// Add the second item to the carousel
[SELECTION_KEY_GOOGLE_HOME]: {
synonyms: [
'Google Home Assistant',
'Assistant on the Google Home',
],
title: 'Google Home',
description: 'Google Home is a voice-activated speaker powered by ' +
'the Google Assistant.',
image: new Image({
url: IMG_URL_GOOGLE_HOME,
alt: 'Google Home',
}),
},
// Add third item to the carousel
[SELECTION_KEY_GOOGLE_PIXEL]: {
synonyms: [
'Google Pixel XL',
'Pixel',
'Pixel XL',
],
title: 'Google Pixel',
description: 'Pixel. Phone by Google.',
image: new Image({
url: IMG_URL_GOOGLE_PIXEL,
alt: 'Google Pixel',
}),
},
},
}));