Amazon Alexa Skill - alexa

I want to ask alexa different sorts of questions and then at the end I want it should ask "Is there anything else you would like to know?" and when I say yes (where yes is working suggestion) it should suggest me according to the intent I am in. Like if I am in
IncityIntent:
'InCityIntent': function () {
speechOutput = '';
speechOutput = "The atmosphere in the city is beautiful. Is there anything else you would like to know";
this.emit(":ask", speechOutput, speechOutput);
'YesIntent': function () {
speechOutput = '';
/*when the user say yes, he should get this output*/
speechOutput = You can learn more about city by trying, alexa what are the best places in the city";
this.emit(":tell",speechOutput, speechOutput);
FoodIntent:
'FoodIntent': function () {
speechOutput = '';
speechOutput = "Food in the city is delicious. Is there anything else you would like to know";
this.emit(":ask", speechOutput, speechOutput);
'YesIntent': function () {
speechOutput = '';
/*change in response here*/
speechOutput = You can learn more about food by trying, alexa what are the best restaurants in the city";
this.emit(":tell",speechOutput, speechOutput);

First thing, do not create custom YesIntent and NoIntent, instead use AMAZON.YesIntent and AMAZON.NoIntent. You can always add utterences to these predefined intents if you want to.
Your issues can be solved in a couple of ways.
Using sessionAttributes:
Add a previousIntent attribute or something to keep a track of the converstation in the sessionAttributes when you receive the initial request, say InCityIntent. And in your AMAZON.YesIntent or AMAZON.NoIntent handler check for the previous intent and reply accordingly.
'InCityIntent': function () {
const speechOutput = "The atmosphere in the city is beautiful. Is there anything else you would like to know";
const reprompt = "Is there anything else you would like to know";
this.attributes['previousIntent'] = "InCityIntent";
this.emit(":ask", speechOutput, reprompt);
}
'Amazon.YesIntent': function () {
var speechOutput = "";
var reprompt = "";
if (this.attributes
&& this.attributes.previousIntent
&& this.attributes.previousIntent === 'InCityIntent' ) {
speechOutput = "You can learn more about city by trying, Alexa what are the best places in the city";
reprompt = "your reprompt";
} else if ( //check for FoodIntent ) {
// do accordingly
}
this.attributes['previousIntent'] = "Amazon.YesIntent";
this.emit(":ask", speechOutput, reprompt);
}
Using STATE handlers
ask-nodejs-sdk v1 has state handlers to generate response based on states. The idea is similar, the sdk will add the sessionAttribute parameter for you and the when will automatically map the handler with respect to that state.
'InCityIntent': function () {
const speechOutput = "The atmosphere in the city is beautiful. Is there anything else you would like to know";
const reprompt = "Is there anything else you would like to know";
this.handler.state = "ANYTHING_ELSE";
this.emit(":ask", speechOutput, reprompt);
}
const stateHandlers = Alexa.CreateStateHandler("ANYTHING_ELSE", {
"AMAZON.YesIntent": function () {
var speechOutput = "You can learn more about city by trying, Alexa what are the best places in the city";
var reprompt = "your reprompt";
this.emit(":ask", speechOutput, reprompt);
},
Once a state is set, then next time the the intent handlers defined in that particular state handler will be triggered. Change your state accordingly and once done, remove it.

Related

Discordjs mentions not always resolving

I am trying to implement a list of users inside a Discord Embed. The list contains a mention for each user and I have been partially successful in accomplishing that. However, it appears that my bot cannot mention everyone, some of the mentions aren't being resolved, and I wonder why is that so. Is it related to the cache? Is there a way to fetch the mentions like fetching users that aren't cached by the bot?
An image of the bot output
leastActiveMembers.forEach((member, index) => {
let mention = `<#${member.user.id}>`;
let lastActive = "";
if (member.user.activity) {
lastActive = new Date(member.user.activity.latestActivityTimestamp).toLocaleString("en-GB");
} else {
lastActive = "Never";
}
lastActive = lastActive.padEnd(20, " ");
leaderBoardRepresentation += `\`${lastActive} ⌛ \`${mention}\n`;
});
const embed = new Discord.MessageEmbed()
.setColor('#DAA520')
.setTitle("🕒 Activity Board ")
.setDescription(leaderBoardRepresentation)
.setThumbnail('https://i.imgur.com/v5RR3ro.png')
.setFooter({ text: footer, iconURL: "" })
I am using discordjs v13.
As #NotTrixxie said, this is Discord's built-in code which we cannot modify. If a user has no relation to the bot (not in the server), it will display it. If you want the username to show, you can display the username instead of mentioning which will work. See below for an example of this:
leastActiveMembers.forEach((member, index) => {
const mention = member.user.username;
let lastActive = '';
if (member.user.activity) {
lastActive = new Date(member.user.activity.latestActivityTimestamp).toLocaleString('en-GB');
} else {
lastActive = 'Never';
}
lastActive = lastActive.padEnd(20, ' ');
leaderBoardRepresentation += `\`${lastActive} ⌛ \`${mention}\n`;
});
const embed = new Discord.MessageEmbed()
.setColor('#DAA520')
.setTitle('🕒 Activity Board ')
.setDescription(leaderBoardRepresentation)
.setThumbnail('https://i.imgur.com/v5RR3ro.png')
.setFooter({
text: footer,
})
Hoped this helped!

How do I select multiple args in a command and assign it to a variable? Discord.js

I want to do so that when I use !pm (user) (some message), my bot will send a private message to the user, although I have no idea how to select everything after the (user) and assign it to a variable, to send it to the user.
My current code looks like this:
module.exports = {
name: 'pm',
description: 'Sends a personal message!',
execute(message, args, client) {
const pmMessage = args[1];
client.users.cache.get('464839066781745167').send(pmMessage);
}
}
Since you know the array index of the pmMessage, with the help of that index, you can use the slice method which returns the array from specified stating to end index.
Eg:
let pmMessage = args.slice(2); //returns array.
Note: If the end index is not specified, then it considers till the last index of the array.
Now, using the join method, you can join all the indexes with whatever specified character. Eg:
let MessageContent = pmMessage.join(' '); //joined by space.
let args = ["UserID","This","represents","the","message","content","to","be","sent"];
console.log(args.slice(1));
console.log(args.slice(1).join(' '));
Try this, I think this should work:
let pm_args = args.slice(1).join(' ')
if(args[0]){
let user = getUserFromMention(args[0])
if(!user){
return message.reply('please mention a user.');
}
return client.users.cache.get(user.id).send(pm_args);
}
return message.reply('please mention a user.');
(This is what I used for mention thingie:)
function getUserFromMention(mention){
if(!mention) return;
if(mention.startsWith('<#') && mention.endsWith('>')){
mention = mention.slice(2, -1);
if(mention.startsWith('!')){
mention = mention.slice(1);
}
return bot.users.cache.get(mention);
}
};
client.on("message", message => {
if(!message.content.startsWith(config.prefix)) return;
const withoutPrefix = message.content.slice(config.prefix.length);
const split = withoutPrefix.split(/ +/);
const command = split[0];
const args = split.slice(1);
// Code...
});

How do i resolve Alexa stop, cancel intents not working

i am using a mish mash of scripts as i do not know coding to be honest, and its working for the most part, but i am struggling with stop, help and cancel during the welcome speech, stop/cancel works ok once you get to the next part, but during the welcome speech, exanmples
User: "Alexa open breckland weather"
Skill: "Welcome to Breckland Weather. Please ask me for the weather, heres a hint, whats the weather like or whats the current conditions."
User: "stop" / User: "cancel" / User: "help"
Skill: "There was a problem with the requested skill's response"
The intents are there and i added utterances in case but still the same so i feel theres sommat in the code thats not right, probably most of it lol, please can one of you kind soles peruse at your leisure and see if you can shed a little light?
exports.handler = (event, context, callback) => {
try {
//console.log(`event.session.application.applicationId=${event.session.application.applicationId}`);
//if (event.session.application.applicationId !== APP_ID) {
// callback('Invalid Application ID');
//}
if (event.session.new) {
onSessionStarted({ requestId: event.request.requestId }, event.session);
}
if (event.request.type === 'LaunchRequest') {
onLaunch(event.request,
event.session, (sessionAttributes, speechletResponse) => {
callback(null, buildResponse(sessionAttributes, speechletResponse));
});
} else if (event.request.type === 'IntentRequest') {
onIntent(event.request,
event.session,
(sessionAttributes, speechletResponse) => {
callback(null, buildResponse(sessionAttributes, speechletResponse));
});
} else if (event.request.type === 'SessionEndedRequest') {
onSessionEnded(event.request, event.session);
callback();
}
} catch (err) {
callback(err);
}
};
const isDebug = false;
const APP_ID = 'amzn1.ask.skill.d31840b5-27f2-4f07-9e19-ec0c73d78b39';
const url_weather = 'http://www.brecklandweather.com/currentout.txt';
const APP_NAME = 'Breckland Weather';
const STR_REPROMPT = '\nPlease ask me for the weather, heres a hint, whats the weather like or whats the current conditions.';
const HELP_MESSAGE = 'You can say whats the weather like, or, you can say exit... What can I help you with?';
const HELP_REPROMPT = 'What can I help you with?';
const STOP_MESSAGE = 'Goodbye!';
function getWeather(intent, session, callback, numLetters) {
let speechOutput = '';
let cardTitle = 'Weather output';
getWebRequest(url_weather, function webResonseCallback(err, data) {
if (err) {
speechOutput = `DOH! somethings done gone bad, self destuct in 3 2 ah, false alarm, still broken though, carry on.`;
callback({}, buildSpeechletResponse(cardTitle, speechOutput, STR_REPROMPT));
} else {
//if (isDebug) {"SolveAnagram::data = " + console.log(data)};
speechOutput = data;
callback({}, buildSpeechletResponse(cardTitle, speechOutput, STR_REPROMPT));
}
});
}
//Simple welcome intent handler
function getWelcomeResponse(callback) {
console.log("START session");
if (isDebug) {console.log("getWelcomeResponse()")}
const cardTitle = APP_NAME;
const speechOutput = 'Welcome to '+APP_NAME+'. '+ STR_REPROMPT;
// If the user either does not reply to the welcome message or says something that is not
// understood, they will be prompted again with this text.
const repromptText = STR_REPROMPT;
const shouldEndSession = false;
callback({}, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
//My effort of code
const handlers = {
'LaunchRequest': function () {
// this.emit('myIntent');
this.emit(':tell', '2 Hello, what would you like to do?');
},
'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');
},
};
//Simple end session intent handler
function handleSessionEndRequest(callback) {
console.log("END session");
const cardTitle = 'Goodbye';
const speechOutput = 'Thanks for using '+APP_NAME+'.';
const shouldEndSession = false;
callback({}, buildSpeechletResponse(cardTitle, speechOutput, null, shouldEndSession));
}
function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
if (isDebug) {console.log(`buildSpeechletResponse(title:${title}, shouldEndSession:${shouldEndSession}, reprompt:${repromptText})`)}
return {
outputSpeech: {
type: 'PlainText',
text: output,
},
card: {
type: 'Simple',
title: `${title}`,
content: `${output}`,
},
reprompt: {
outputSpeech: {
type: 'PlainText',
text: repromptText,
},
},
shouldEndSession,
};
}
function buildResponse(sessionAttributes, speechletResponse) {
return {
version: '2.0',
response: speechletResponse,
sessionAttributes: sessionAttributes,
};
}
//----------------- Web service helper ----------------------//
var http = require('http');
function getWebRequest(url,doWebRequestCallBack) {
try
{
http.get(url, function (res) {
var webResponseString = '';
if (isDebug) {console.log('Status Code: ' + res.statusCode)}
if (res.statusCode != 200) {
doWebRequestCallBack(new Error("Non 200 Response"));
return;
}
res.on('data', function (data) {
webResponseString += data;
});
res.on('end', function () {
//if (isDebug) {console.log('getWebRequest::Got some data: '+ webResponseString)};
//the weather isn't JSON so just return the string
//var webResponseObject = JSON.parse(webResponseString);
doWebRequestCallBack(null, webResponseString);
});
}).on('error', function (e) {
if (isDebug) {console.log("Communications error: " + e.message)}
doWebRequestCallBack(new Error(e.message));
});
}
catch(err)
{
doWebRequestCallBack(new Error(err.message));
}
}
// --------------- Events -----------------------
/**
* Called when the session starts.
*/
function onSessionStarted(sessionStartedRequest, session) {
//console.log(`onSessionStarted requestId=${sessionStartedRequest.requestId}, sessionId=${session.sessionId}`);
}
/**
* Called when the user launches the skill without specifying what they want.
*/
function onLaunch(launchRequest, session, callback) {
//console.log(`onLaunch requestId=${launchRequest.requestId}, sessionId=${session.sessionId}`);
// Dispatch to your skill's launch.
getWelcomeResponse(callback);
}
/**
* Called when the user specifies an intent for this skill.
*/
function onIntent(intentRequest, session, callback) {
const intent = intentRequest.intent;
const intentName = intentRequest.intent.name;
console.log(" ");
console.log("== New Intent ==");
console.log(`onIntent(${intentName})`);
if (intentName === 'GetWeather') {
getWeather(intent, session, callback,1);
}
}
/**
* Called when the user ends the session.
* Is not called when the skill returns shouldEndSession=true.
*/
function onSessionEnded(sessionEndedRequest, session) {
//console.log(`onSessionEnded requestId=${sessionEndedRequest.requestId}, sessionId=${session.sessionId}`);
// Add cleanup logic here
}
Your design pattern is quite confusing. But I see where your problem is. You are not using your handlers object for handling intent requests at all. According to your design pattern you can make changes as follows:
/**
* Called when the user specifies an intent for this skill.
*/
function onIntent(intentRequest, session, callback) {
const intent = intentRequest.intent;
const intentName = intentRequest.intent.name;
console.log(" ");
console.log("== New Intent ==");
console.log(`onIntent(${intentName})`);
if (intentName === 'GetWeather') {
getWeather(intent, session, callback,1);
}else if(intentName === 'AMAZON.StopIntent'){
getStopResponse(intent, session, callback,1)
}else if(intentName === 'AMAZON.HelpIntent'){
getHelpResponse(intent, session, callback,1)
}
}
And response builder function as follows:
//Simple welcome intent handler
function getStopResponse(callback) {
console.log("START session");
if (isDebug) {console.log("getStopResponse()")}
const cardTitle = APP_NAME;
const speechOutput = STOP_MESSAGE
const repromptText = STOP_MESSAGE;
const shouldEndSession = true;
callback({}, buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
Similar one would go for getHelpResponse(). I will leave that up to you.
Tell me if this helps you.

Testing different utterances for a match

I am new to programming for Amazon Echo. I am using Node.js and am trying to return a different response based on my utterance of a name.
For example if I say the name "David" or "James" or "Benjy" Alexa should just say "Welcome [and the name I said]" but if I say "Jonathan" it should say "Yay! Welcome home Jonathan".
But when I say "Jonathan" it just says "Welcome Jonathan".
I have been modifying the basic alexa-skills-kit-color-expert Lambda and have modified the setColorInSession() function in that code. I have renamed that function setAndWelcomePerson().
I have tried:
to use an if statement to test my utterance and have Alexa reply based on my utterance
to give different examples of utterances to try to teach Alexa to differentiate between one name and the next.
None of this seems to work. Please tell me what I'm doing wrong and suggestions to fix. Some code below:
The setAndWelcomePerson() function from my Lambda code:
/**
* Sets the name of the person(s) and welcomes them.
*/
function setAndWelcomePerson(intent, session, callback) {
var cardTitle = intent.name;
var whoToGreetSlot = intent.slots.Person;
var repromptText = null;
var sessionAttributes = {};
var shouldEndSession = false;
var speechOutput = "";
if (whoToGreetSlot) {
var whoToGreet = whoToGreetSlot.value;
sessionAttributes = createWhoToGreetAttributes(whoToGreet);
if (whoToGreet === "Jonathan") {
speechOutput = "Yay! Welcome home " + whoToGreet + "!";
} else {
speechOutput = "Welcome " + whoToGreet + ".";
}
} else {
speechOutput = "I'm not sure who you want me to welcome. Please try again.";
}
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
My intent schema:
{
"intents": [
{
"intent": "WhoShouldBeGreeted",
"slots": [
{
"name": "Person",
"type": "LITERAL"
}
]
},
{
"intent": "AdditionalGreetingRequest",
"slots": []
}
]
}
My sample utterances:
WhoShouldBeGreeted {Sam and Cat|Person}
WhoShouldBeGreeted {Jonathan|Person}
WhoShouldBeGreeted {James|Person}
WhoShouldBeGreeted {Benji|Person}
WhoShouldBeGreeted welcome {Sam and Cat|Person}
WhoShouldBeGreeted welcome {Jonathan|Person}
WhoShouldBeGreeted welcome {James|Person}
WhoShouldBeGreeted welcome {Benji|Person}
Thank you for your help.
You are using a "LITERAL" slot type. (This is discouraged, but it is still supported.) That means you are just recognizing a word. Spoken words have no case. But the === operator in Javascript is case sensitive. If you check your logs, I suspect that when you say "Jonathan" what you get is "jonathan", which your match then fails.
To fix this you can change your compare to lower case, or change the operator to a case insensitive string compare (see here).
Another approach would be to not use the LITERAL slot type, and use the AMAZON.US_FIRST_NAME instead. Since this knows it is a name, it returns it capitalized.

Getting object or array value for Auth on Firebase

I'm using angularfire 1.1.1 to store my apps objects and each object creates associated indexes. So when a user is created, that user is added to the 'users' table and then the users index table gets keyed with the UID and points to the actual user's id.
When the main state is called, I run a checkAuth() method to see if a user is signed in. If so, then I want to assign $rootScope.auth = {id:userID, role: role} etc.
The function works great in my login method but i don't know how to grab the value from my checkAuth() method. I've tried $value on both $firebaseObject and $firebaseArray, also tried to call them with [0] since there is only one id value in the table for each user's uid.
The sloppy regex is for changing the semi-colon from SimpleLogin:47 to SimpleLogin-47 for keying to the index.
Here's the code that doesn't work:
function authCheck(){
var getAuth = $firebaseAuth(Data.ref);
console.log('signed in as', getAuth.$getAuth().uid);
var uid = getAuth.$getAuth().uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
var userIndexRef = Data.ref.child('index/users/uid/'+uid);
var userIndexArray = $firebaseArray(userIndexRef);
var userIndexObject = $firebaseObject(userIndexRef);
console.log(userIndexArray, userIndexObject);
var realId = '';
angular.forEach(userIndexObject, function(key, id){
realId = id;
$rootScope.auth = realId;
return realId;
});
}
Here's the login code that does work:
function login(email, pass) {
ref.authWithPassword({email:email,password:pass}, function(error, authData){
if (error) {
console.log(error);
} else {
console.log('signed in as',authData.uid);
var uid = authData.uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
angular.forEach(Data.dataObject.index.users.uid[uid],function(id, key){
$rootScope.role = Data.dataObject.users[id].role;
$rootScope.auth = {authData:authData, id:id, role:Data.dataObject.users[id].role};
});
}
});
}
If anyone sees where I've messed up, I'll be happy to know. Here's the repo https://github.com/irthos/medviz if it helps. Thank you very much!

Resources