Asking for location permissions - dialogflow-es

I have an action that is requesting location, but I'm a little confused by the Dialogflow setup of this. This is my code:
app.intent('bus_stop_nearby_permission', (conv) => {
conv.ask(new Permission({
context: 'To get nearby bus stops',
permissions: 'DEVICE_PRECISE_LOCATION',
}));
});
app.intent('bus_stop_nearby', (conv, input, granted) => {
if (granted) {
conv.close(`Location was granted ${JSON.stringify(conv)}`);
} else {
conv.close(`Location was not granted!`);
}
});
In Dialogflow the initial intent bus_stop_nearby_permission is triggered by asking for bus stops near me with a training phrase, there is no event attached to this dialog. The follow-up intent bus_stop_nearby has the action_intent_PERMISSION event attached to it and no training phrases. Right now my action asks for permissions but doesn't understand any confirmation input, and just defers to the fallback intent when I say yes to it.
Screenshots of bus_stop_nearby intent:
Screenshot of bus_stop_nearby_permission:
Do I need to add follow up contexts for when the user approves the location request?

The event should be actions_intent_PERMISSION with an "s" at the end of "action".
Easy and common typo to miss.

Related

Account Linking Actions On Google

After Sign is done, my output for "Get Signin" intent is not displayed.
Using Google-Sign in
app.intent("redeem", (conv) => {
conv.ask(new SignIn("To redeem "));
})
app.intent("Get Signin", (conv, params, signin) => {
if (signin.status === 'OK') {
const payload = conv.user.profile.payload;
conv.ask(`I got your account details ${payload.name} , how would you like to redeem? `)
conv.ask(new Suggestions(['QR code'], ['code']));
}
else {
conv.close("Please sign in to redeem");
}
})
After a successful sign in I get this message:
Dialogflow Get Signin (top part):
Dialogflow Get Signin (bottom part):
When the Sign-In completes, it triggers the actions_intent_SIGN_IN Dialogflow event. So your "Get Signin" Intent needs to have this set in the Event field, with no training phrases.
It might look something like this
Since you don't have an Event or Training phrases set, that Intent will never be triggered. Instead, when the Sign-in completes, Actions will send the Event, but since there is nothing setup to handle the event in Dialogflow, it will fail to do anything, so it will exit with the error about not responding.

Regarding retrieving prompts

[We have a Dialogflow bot consisting of two intents. Each intent contains some set of questions.
The user answers the questions(prompts) and this process continues. We are getting the fulfillment text only after the intent is completed but we need to get the fulfillment text(Each and every prompt) after completing every question in that particular intent.
Help us in finding the solution.
You can use webhook for slot filling. (under the "Enable webhook call for this intent", enable Enable webhook call for slot filling button). By doing this, you can still stay in intent handler function and prompt what you need until you can finish your steps.
For example:
function flight(agent) {
const city = agent.parameters['geo-city'];
const time = agent.parameters['time'];
const gotCity = city.length > 0;
const gotTime = time.length > 0;
if(gotCity && gotTime) {
agent.add(`Nice, you want to fly to ${city} at ${time}.`);
} else if (gotCity && !gotTime) {
agent.add('Let me know which time you want to fly');
} else if (gotTime && !gotCity) {
agent.add('Let me know which city you want to fly to');
} else {
agent.add('Let me know which city and time you want to fly');
}
}
Also you can use this functionality on actions-on-google library.
Check for more information:
Webhook for slot filling
Enable Webhook for Slot Filling. Dialogflow will call your server to see if you can provide the pending information that your user didn’t.

How to get device coarse location for each webhook request in actions on google

Hi i'm trying to get device coarse location by getting permission from user.But i required to get device location details for each webhook request without asking permission again and again.So I'm bit confused how to do this one.
Here is the below code which i tried.
const {Permission} = require('actions-on-google');
const {WebhookClient} = require('dialogflow-fulfillment');
const agent = new WebhookClient({ request: req, response: res });
function x(agent){
conv.ask(new Permission({context:'To Locate You',permissions:'DEVICE_COARSE_LOCATION'}));
}
function userinfo(agent){
var conv=agent.conv();
var resp=conv.arguments.get('PERMISSION');
console.log(conv.device.location);
if(resp){
var country=conv.device.location.country;
var speech="you are located in "+country;
conv.ask(speech);
agent.add(conv);
}else{
conv.ask('Sorry, I could not figure out where you are');
agent.add(conv);
}
}
Please check the helper functions here. You need to do the following:
Create an intent to ask for permission.
In that intent, ask the permission you want
Create second intent to capture user's response to intent by putting the Dialogflow event actions_intent_PERMISSION to that intent.
In the webhook handle of the second intent check for confirmation.
Ask Permission in First Intent
app.intent('FIRST_INTENT_NAME', (conv) => {
// Choose one or more supported permissions to request:
// NAME, DEVICE_PRECISE_LOCATION, DEVICE_COARSE_LOCATION
const options = {
context: 'To address you by name and know your location',
// Ask for more than one permission. User can authorize all or none.
permissions: ['NAME', 'DEVICE_PRECISE_LOCATION'],
};
conv.ask(new Permission(options));
});
Capture result in Second Intent
app.intent('SECOND_INTENT_NAME', (conv, params, confirmationGranted) => {
const {name} = conv.user;
if (confirmationGranted) {
if (name) {
conv.ask(`I'll send the driver you're way now ${name.display}.`);
}
}
});
For exact understanding with code example, check out this GitHubb example link.

Why doesn't the permission for a name work?

I'm trying to allow a permission in Google Assistant, but the simulator just asks to "repeat the answer" when asking for a name. Here is the code for permission.
app.intent('Default Welcome Intent', (conv) => {
conv.ask(new Permission({
context: 'Hi there, to get to know you better',
permissions: 'NAME'
}));
});
On deploying the code via Firebase, no errors are thrown.
Thanks in advance.
In your agent Default Welcome Intent is the intent which asks for NAME permission.
You will have to implement another intent to handle this permission. Lets call it user_info intent.
So when Actions On Google asks the question, and the user responds “yes” or “no” (grants or declines); Actions On Google will then send an event called “actions_intent_PERMISSION” to DialogFlow. We’ll use that event to trigger this particular intent. Once the intent is triggered, we’ll make sure to send the “user_info” action to our application.
In the application, we’ll register the “user_info” action and make sure to check whether the user has granted or declined the permissions. For that, we call the isPermissionGranted helper method.
app.intent('user_info', (conv, params, permissionGranted) => {
if (!permissionGranted) {
throw new Error('Permission not granted');
}
const {requestedPermission} = conv.data;
if (requestedPermission === 'NAME') {
conv.user.storage.name = conv.user.name.display;
return conv.close(responses.sayName(conv.user.storage.name));
}
throw new Error('Unrecognized permission');
});

Calling Another Alexa intent from within LaunchRequest

I am working on an Alexa skill where I would like to redirect user to one intent when he opens the skill via LaunchRequest.
User says Open xyz skill
LaunchRequest receives this and forwards the request to another intent.this.emit('AnotherIntent')
AnotherIntent has a SLOT which is required for its functioning.
I have setup the SLOT as required and AnotherIntent does work perfectly fine when invoked on its own.
However when I Launch the skill and tries to call AnotherIntent from within it as mentioned in Step 2 above, Alexa skill fails to launch.
One more thing to note is when I Test the same Alexa skill from within the skill builder for this scenario, the output json correctly shows me the SLOT being elicited. Not sure what is happening when I am trying to run it from Echo device.
I am using NodeJS and Lambda to deploy my Alexa handlers.
Any help would be appreciated.
Further reference based on the comment -
Handlers -
var handlers = {
'LaunchRequest': function () {
console.log("LaunchRequest::" + JSON.stringify(this.event.request));
this.emit('fooIntent');
},
'SessionEndedRequest': function () {
console.log('session ended!');
},
'fooIntent': function () {
const intentObj = this.event.request.intent;
if (!intentObj || (intentObj && !intentObj.slots.WHEN.value)) {
console.log('fooIntent::UserId' + this.event.session.user.userId);
const slotToElicit = 'WHEN';
const speechOutput = 'Ask a question here ?';
const repromptSpeech = speechOutput;
console.log("emitting elict now");
this.emit(':elicitSlot', slotToElicit, speechOutput, repromptSpeech);
} else {
// SLOT is filled, let's query the database to get the value for the slot.
console.log("fooIntent intent:something is requested for " + this.event.request.intent.slots.WHEN.value);
// All the slots are filled (And confirmed if you choose to confirm slot/intent)
fooIntentFunction(this,this.event.request.intent.slots.WHEN.value);
}
},
'AMAZON.HelpIntent': function () {
var speechOutput = "Need to come up with one.";
var reprompt = "What can I help you with?";
this.emit(':ask', speechOutput, reprompt);
},
'AMAZON.CancelIntent': function () {
this.emit(':tell', 'Goodbye!');
},
'AMAZON.StopIntent': function () {
this.emit(':tell', 'Goodbye!');
}
};
JSON Request captured in LaunchRequest
{
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.972bb705-d181-495e-bf60-991f2bd8fbb1",
"timestamp": "2017-12-30T21:35:21Z",
"locale": "en-US"
}
JSON Request captured in the Intent when invoked from LaunchRequest. It shows that intent is not set then. I believe that is why it keeps failing when I try to emit elicit in the fooIntent implementation as shown above.
{
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.972bb705-d181-495e-bf60-991f2bd8fbb1",
"timestamp": "2017-12-30T21:35:21Z",
"locale": "en-US"
}
Amit
As specified in Amazon's documentation, the dialog interface is meant to fill all required slots of a specific intent:
The questions and answers are intended to gather and confirm values for all of the intent’s required slots. The conversation continues until all slots needed for the intent are filled and confirmed.
In your case, the user's request is not an intent (i.e. of the IntentRequest type), but a LaunchRequest. As such,it has no interaction model and no slots to elicit, even though it is processed by an intent handler.
You should get your Skill to work as intended with a deep invocation, like
Alexa, tell xyz skill to make me a sandwich
(if the sandwich intent, or in your case the fooIntent, has a WHEN slot to elicit).
Hope this helps!
try this,
this.emitWithState("IntentName");
Hope this helps. all the best :)
Calling an intent from another intent can be simply done using the following snippet - \
this.emit("Intent name")
In the response of your first intent, give the name of the intent you wish to call.

Resources