Alexa not invoking the Intent - alexa

I was trying to make an alexa skill, which is based on the fact skill of the alexa's blueprint. I've made a custom Intent named "myIntent", which has a variable "{myName}" or slot type "myNameSlot". I've added multiple values like "Dhruv,User,My User" (all are separate values).
So, I tried to launch my Alexa skill in Test via the simulator. It is launching all the in-built intents just fine. However, when I try to launch my custom Intent, it doesn't launch.I wrote the same utterances, however, it is not being invoked.
Here's my Lambda Function's code : https://pastebin.com/7CrdMffW
/* eslint-disable func-names */
/* eslint quote-props: ["error", "consistent"]*/
/**
* This sample demonstrates a simple skill built with the Amazon Alexa Skills
* nodejs skill development kit.
* This sample supports multiple lauguages. (en-US, en-GB, de-DE).
* The Intent Schema, Custom Slots and Sample Utterances for this skill, as well
* as testing instructions are located at https://github.com/alexa/skill-sample-nodejs-fact
**/
'use strict';
const Alexa = require('alexa-sdk');
//=========================================================================================================================================
//TODO: The items below this comment need your attention.
//=========================================================================================================================================
//Replace with your app ID (OPTIONAL). You can find this value at the top of your skill's page on http://developer.amazon.com.
//Make sure to enclose your value in quotes, like this: const APP_ID = 'amzn1.ask.skill.bb4045e6-b3e8-4133-b650-72923c5980f1';
const APP_ID = undefined;
const SKILL_NAME = 'Space Facts';
const GET_FACT_MESSAGE = "Here's your fact: ";
const HELP_MESSAGE = 'You can say tell me a space fact, or, you can say exit... What can I help you with?';
const HELP_REPROMPT = 'What can I help you with?';
const STOP_MESSAGE = 'Goodbye!';
//=========================================================================================================================================
//TODO: Replace this data with your own. You can find translations of this data at http://github.com/alexa/skill-sample-node-js-fact/data
//=========================================================================================================================================
const data = [
'A year on Mercury is just 88 days long.',
'Despite being farther from the Sun, Venus experiences higher temperatures than Mercury.',
'Venus rotates counter-clockwise, possibly because of a collision in the past with an asteroid.',
'On Mars, the Sun appears about half the size as it does on Earth.',
'Earth is the only planet not named after a god.',
'Jupiter has the shortest day of all the planets.',
'The Milky Way galaxy will collide with the Andromeda Galaxy in about 5 billion years.',
'The Sun contains 99.86% of the mass in the Solar System.',
'The Sun is an almost perfect sphere.',
'A total solar eclipse can happen once every 1 to 2 years. This makes them a rare event.',
'Saturn radiates two and a half times more energy into space than it receives from the sun.',
'The temperature inside the Sun can reach 15 million degrees Celsius.',
'The Moon is moving approximately 3.8 cm away from our planet every year.',
];
//=========================================================================================================================================
//Editing anything below this line might break your skill.
//=========================================================================================================================================
const handlers = {
'LaunchRequest': function () {
// this.emit('myIntent');
this.emit(':tell', '2 Hello, what would you like to do?');
},
'myIntent': function () {
const factArr = data;
const factIndex = Math.floor(Math.random() * factArr.length);
const randomFact = factArr[factIndex];
const speechOutput = GET_FACT_MESSAGE + randomFact;
this.response.cardRenderer(SKILL_NAME, randomFact);
this.response.speak('Halo ' + speechOutput);
this.emit(':responseReady');
},
'AMAZON.HelpIntent': function () {
const speechOutput = HELP_MESSAGE;
const reprompt = HELP_REPROMPT;
this.response.speak(speechOutput).listen(reprompt);
this.emit(':responseReady');
},
'AMAZON.CancelIntent': function () {
this.response.speak(STOP_MESSAGE);
this.emit(':responseReady');
},
'AMAZON.StopIntent': function () {
this.response.speak(STOP_MESSAGE);
this.emit(':responseReady');
},
};
exports.handler = function (event, context, callback) {
const alexa = Alexa.handler(event, context, callback);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
I'm not sure what's happening here.
EDIT: This is the information about my Intent and custom slot :
Intent Name : myIntent.
Utterances :
1.) tell me about {data_of_intent}
2.) what is the synopsys of {data_of_intent}
Intent Slots (1) : data_of_intent of type my_custom_type.
Custom Slot Type Values :
1.) one piece
2.) Flower Dream
3.) Kanai kun
4.) Has the rain stopped?

I double checked the JSON I was receiving on the first hit.The issue was that shouldEndSession was set to true and that's because, in NodeJS, shouldEndSession is set to true in :tell and cannot be overridden.
I was using :
this.emit(':tell', '2 Hello, what would you like to do?');.
I changed it to :
this.emit(':ask', '2 Hello, what would you like to do?');
and it worked.
There's a Github thread for the same : https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs/issues/64

Related

(discord.js) How to set a time limit on a command?

I am trying to make a Judge bot for my server that will give the person who used the command the role "Plaintiff", and give the person that they mentioned the "Defendant" role. Everything works perfectly as intended except the fact that multiple trials can be started at the same time. Like if someone uses the command and it makes them the plaintiff and a 2nd person the defendant, if a 3rd person uses the command on a 4th person they will become a defendant and plaintiff as well. I want to make it so that while the events of the command are playing out that nobody else in the server can use the command until the 1st trial ends. I have tried to give the entire server the role "jury" and make it so that if anyone has the role "jury" they can't use the command but i couldn't ever get that to work. Also I tried to set a time limit for the command and that didn't work at all either. I have no clue how to get this working and any advice is appreciated!! Thanks!!!
client.on("message", message => {
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === "sue") {
let member1 = message.mentions.members.first();
message.member.roles.add("797738368737345536")
member1.roles.add("797738235715256331");
message.guild.members.cache.forEach(member => member.roles.add("797743010346565672"))
message.channel.send("Court is now in session.")
client.channels.cache.find(channel => channel.name === 'courtroom').send( + " **All rise.**");
client.channels.cache.find(channel => channel.name === 'courtroom').send("Plaintiff, you have 2 minutes to state your case.");
setTimeout(function(){
client.channels.cache.find(channel => channel.name === 'courtroom').send("Thank you Plaintiff. Defendant, you now have 2 minutes to defend yourself.");
}, 120000);
setTimeout(function(){
client.channels.cache.find(channel => channel.name === 'courtroom').send("Thank you. The court may be seated as we turn to the jury for their verdict.");
}, 240000);
const Responses = [
"The Jury hereby finds you.... **GUILTY!** You will be sentanced to 10 minutes in jail.",
"The Jury hereby finds you.... **NOT GUILTY!** You are free to go. The Jury is dismissed."
];
const Response = Responses[Math.floor(Math.random() * Responses.length)];
setTimeout(function(){
client.channels.cache.find(channel => channel.name === 'courtroom').send(Response)
if (Response === "The Jury hereby finds you.... **NOT GUILTY!** You are free to go. The Jury is dismissed." ) {
message.member.roles.remove("797738368737345536")
member1.roles.remove("797738235715256331");
message.guild.members.cache.forEach(member => member.roles.remove("797743010346565672"))
}
if (Response === "The Jury hereby finds you.... **GUILTY!** You will be sentanced to 10 minutes in jail.") {
message.member.roles.remove("797738368737345536")
member1.roles.add("797738617338069002")
member1.roles.remove("797738235715256331");
message.guild.members.cache.forEach(member => member.roles.remove("797743010346565672"))
}
}, 250000);
setTimeout(function(){
member1.roles.remove("797738617338069002");
}, 850000);
}
});
You could create a file, so nobody is able to use the command while the file exists.
const fs = require("fs");
if (command_gets_executed) { // If the command gets executed
if (fs.existsSync("./commandAlreadyUsed")) { // Checking if the file exists
// YOUR CODE - When the command should not be usable
} else {
fs.writeFileSync("./commandAlreadyUsed"); // Creating the file
// YOUR CODE - When nobody else used the command before
}
}
And if you want the command usable again just use fs.unlinkSync("./commandAlreadyUsed").
You can try to use a CronJob to set a time limit, I used it before for a similar case, may be it can be useful for you

Alexa Skills Dialog Management: how to repeat last intent without specifing its utterances again

I'm developing my first Alexa skill and I want to try to improve its dialog management.
My skill has several intents: one to get the temperature indoor, one to get the humidity and so on. Every intent has one slot that represents the floor/room of my house so the typical question to Alexa is "What's the temperature on the first floor?"
Every time intent is executed it stores the slot in a session attribute so I can handle a conversation like this:
me: "Alexa what's the temperature on the first floor?"
Alexa: "The temperature on the first floor is 24 degrees"
me: "and the humidity?"
Alexa: "The humidity on the first floor is 50%"
The next step that I'm trying to implement is this type of dialog:
me: "Alexa what's the temperature on the first floor?"
Alexa: "The temperature on the first floor is 24 degrees"
me: "and on the second floor?"
Alexa: "The temperature on the second floor is 26 degrees"
In practice, I need to launch the last executed intent without saying its utterances.
I was thinking of creating a new generic intent that receives only the slot and then dispatches the request to the last executed intent.
I can keep track of the last intent executed saving its ID in a session attribute.
Is there a better way to do this?
Every suggestion is welcome because I am developing Alexa skills since last Monday! :-)
Thanks a lot.
You're on the right track. The thing to remember is you can have one intent for multiple slots and NOT require them all.
Here's how you can create a single intent for all of it.
The sample utterances are:
How are things on the {floor}
And on the {floor}
What is the {condition}
What is the {condition} on the {floor}
Then you create the "condition" and "floor" slot types, filling them with appropriate sample values like "temperature" for condition and "first floor" for floor. Then make sure to assign those slot types to the slots in your intent.
Then your handler code looks like this...
const conditionIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'conditionIntent';
},
handle(handlerInput) {
var speakOutput = "";
var condition = "";
var floor = "";
const attributesManager = handlerInput.attributesManager;
const attributes = attributesManager.getSessionAttributes();
if (handlerInput.requestEnvelope.request.intent.slots.condition.hasOwnProperty('value')) {
condition = handlerInput.requestEnvelope.request.intent.slots.condition.value;
} else if (attributes.hasOwnProperty('condition')) {
if(attributes.condition !== "") condition = attributes.condition;
}
if (handlerInput.requestEnvelope.request.intent.slots.floor.hasOwnProperty('value')) {
floor = handlerInput.requestEnvelope.request.intent.slots.floor.value;
} else if (attributes.hasOwnProperty('floor')) {
if(attributes.floor !== "") floor = attributes.floor;
}
if (floor !== "" && condition === ""){
speakOutput = "Here's the conditions for the " + floor;
} else if (floor === "" && condition !== ""){
speakOutput = "Here's the " + condition + " throughout the house";
} else if (floor !== "" && condition !== ""){
speakOutput = "Here's the " + condition + " on the " + floor;
} else {
speakOutput = "I have no idea what you're saying. Are you okay?"
}
attributes.floor = floor;
attributes.condition = condition;
attributesManager.setSessionAttributes(attributes);
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt('What else can I tell you?')
.getResponse();
}
};
I haven't written the actual code to present the values, just placeholder responses, but you should get the idea. Add more carrier phrases that contain one or both slot types to make this handle more ways people might ask for this info.

Best way to get arguments from string by user for chat bot

I need to accept 2 arguments: first is time argument for example "1m", "2h 42m", "1d 23h 3s", second is text. I thought I can just convert input string to array and split it into 2 array using regex maybe, first with "d", "h", "m" and "s", second everything else and convert in back to string. but then I realize I'll need 3rd argument which gonna be optional target channel (dm or current channel, where command been executed), and also what if user want to include 1m in his text (it's reminder command)
The easiest way to do this is to have the user seperate each argument by a comma. Although this creates the issue where the user can't user a comma in their text part. So if that isn't an option, another way to do it is to get the message content and start by stripping parts of it away. You begin by grabbing the time portion with a regex. Then you look for channel mentions and strip those away. What you're left with should solely be the text.
Below is some (non-tested) code which could lead you in the right direction. Give it a try and let me know if you have any problems
let msg = {
content: "1d 3h 45m 52s I feel like 4h would be to long <#222079895583457280>",
mentions: {
channels: ['<#222079895583457280>']
}
};
// Mocked Message object for testing purpose
let messageObject = {
mentions: {
CHANNELS_PATTERN: /<#([0-9]+)>/g
}
}
function handleCommand (message) {
let content = message.content;
let timeParts = content.match(/^(([0-9])+[dhms] )+/g);
let timePart = '';
if (timeParts.length) {
// Get only the first match. We don't care about others
timePart = timeParts[0];
// Removes the time part from the content
content = content.replace(timePart, '');
}
// Get all the (possible) channel mentions
let channels = message.mentions.channels;
let channel = undefined;
// Check if there have been channel mentions
if (channels.length) {
channel = channels[0];
// Remove each channel mention from the message content
let channelMentions = content.match(messageObject.mentions.CHANNELS_PATTERN);
channelMentions.forEach((mention) => {
content = content.replace(mention, '');
})
}
console.log('Timepart:', timePart);
console.log('Channel:', channel, '(Using Discord JS this will return a valid channel to do stuff with)');
console.log('Remaining text:', content);
}
handleCommand(msg);
For the messageObject.mentions.CHANNEL_PATTERN look at this reference

OpenLayers loop layers function

In OpenLayers, I have a button (show), when I press on it, I got a layer on the map
My question: How can I show many layers consequently With a certain frame rate
(Something like a loop!)
to show a new/other layer every X seconds, use setInterval
let's assume that you somehow got an array of dates for which you have tiles, and a function displayLayerByDate(dateObject) that can show the layer.
function animatedLayers(arrayOfDates) {
let currentIdx = 0;
const handle = setInterval(function() {
const currentDate = arrayOfDates[currentIdx];
displayLayerByDate(dateObject);
}, 5000);
}

Channel API closes a channel

First off, thank you #Moishe for the very useful API. I'm having a little timeout problem, maybe someone knows the answer. Here's how I open the channel:
var openChannel = function () {
var channel = new goog.appengine.Channel($('#token').val());
var socket = channel.open();
socket.onopen = function () {};
socket.onmessage = function (m) {
var message = JSON.parse(m.data);
// do stuff
};
socket.onerror = function (error) { alert(error); };
socket.onclose = openChannel;
};
openChannel();
This works fine, I post my messages and they go to the other clients pretty quickly. But if I stay on the page for roughly 15 minutes, the server loses track of my channel. In dev, it throws an error (which I saw was a known bug: http://www.mail-archive.com/google-appengine#googlegroups.com/msg44609.html). But in prod, it still ignores messages on that channel after about 15 minutes.
We fixed it by adding a setInterval(getSomeUrl, everyMinute) to the page, but we'd rather not have to do that. I noticed in Moishe's last commit for the trivia game sample that he took out a keep-alive. I didn't understand how he replaced it, and what he meant by onopen is reliable:
http://code.google.com/p/trivia-quiz/source/browse/trunk/src/index.html
Update: Server side code is
class Home(BaseHandler):
def get(self):
self.checkUser()
if self.user:
userId = self.user.user_id()
token = channel.create_channel(userId)
chatClients[userId] = token
self.model['token'] = token
players = self.checkChatRoom()
self.model['users'] = players
self.model['messages'] = map(lambda k:db.get(k), self.chat_room.messages) # TODO: Replace this line and the next with a query
self.model['messages'] = sorted(self.model['messages'], key=lambda m: m.timestamp, reverse=True)
self.writeTemplate('index.html')
BaseHandler is just a base class I use for all my GAE handlers, it provides checkUser which redirects if the user isn't logged in, and it provides writeTemplate which takes what's in self.model and writes it in a template. It's just a proof of concept, so no cache or anything else other than what's above.

Resources