I have an alexa skill that plays a sound file on request and then plays a message and stops playing it when the user says stop. I use an end session statement in the stop intent. However, after saying stop once, if you say Alexa stop again it plays the message again, telling me that the skill is still active. How do you give a command to completely exit from the skill?
Here's my current stop intent:
'AMAZON.StopIntent': function() {
//output to available screen
makeTemplate.call(this, 'stop');
this.response.speak('Ok. I sent a practice tip to your Alexa app.').audioPlayerStop();
this.emit(':responseReady');
this.response.shouldEndSession(true);
},
You could take advantage of the state machine within Alexa, I would suggest to have different state, besides the default regular one, to have the StopIntent there. In this case you could switch to this state when you are playing the sound and only then your particular Stop behavior will work, there you can return to the regular state which wouldn't have a default behavior on your skill so it will run the default one from the Alexa itself closing your skill.
In this code you can have a basic idea on how this could work, though for sure there is stuff missing, but the important things are the this.handler.state which controls in what state is the session at the moment, and Alexa.CreateStateHandler(state, intents) which gets as parameter the name of a particular state and the particular behavior for the intents on that state.
const Alexa = require('alexa-sdk');
const defaultHandlers = {
PlayIntent: function() {
// move to state 'PLAY'
this.handler.state = 'PLAY'
// Code to play
}
}
const playingHanders = Alexa.CreateStateHandler('PLAY', {
PlayIntent: function() {
// Code to play
},
'AMAZON.StopIntent': function() {
//output to available screen
makeTemplate.call(this, 'stop');
// move to default state
this.handler.state = ''
this.response.speak('Ok. I sent a practice tip to your Alexa app.').audioPlayerStop();
this.emit(':responseReady');
this.response.shouldEndSession(true);
}
})
module.exports.skill = (event, context, callback) => {
const alexa = Alexa.handler(event, context, callback);
alexa.appId = APP_ID
alexa.registerHandlers(defaultHandlers, playingHanders)
alexa.execute();
}
There are many tutorials on this on internet so you can find better ideas on how to take advantage of this.
Related
I am new to alexa. I created a custom intent to just repeat a custom text (no slots etc). However my custom intent is never invoked. saved and deployed my code. I get empty JSON request and response - meaning my intent is never invoked. I saved the code and deployed. Adding below the intent node js code handler.
// Begin Code added by Gopalakrishnan for Handling Check Workday Inbox
const checkInboxIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'checkInbox';
},
handle(handlerInput) {
const speakOutput = 'I am here to check Workday Inbox!';
return handlerInput.responseBuilder
.speak(speakOutput)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
/*End*/
There is nothing wrong with the code provided here. Here are a couple of things I recommend checking:
Check that your handler is added to the skill with the addRequestHandlers function in the skill builder. Typically this builder is at the bottom of your index.js file.
Check that the intent name "checkInbox" is spelled the same in both your interaction model and canHandle method.
Make sure that your interaction model with the added checkInbox intent has been built in the skills console.
Make sure that you are launching your skill before trying to invoke this intent.
I just began trying to learn how to write my first Discord bot this morning so I am very inexperienced with discord.js, but I am familiar with JavaScript. However I have been searching for a couple of hours trying to find a way to call a function whenever a user in my server receives or loses a role.
In my server I have added the Patreon bot which assigns a role to users who become patrons. And I would like to create a custom bot that posts "hooray username" in my general channel when a user receive the patron role.
I can not find any example that shows how to detect when a user gains or loses a role. Is it possible to do this simply using an event? Or would I possibly need to periodically iterate over all users and maintain a list of their current roles while checking for changes?
I apologize that my question doesn't include any code or examples but I haven't made any progress and am reaching out to the SO community for guidance.
You want to use the event guildMemberUpdate.
You can compare the oldMember state to the newMember state and see what roles have changed.
This is not the most elegent solution but will get the job done.
client.on('guildMemberUpdate', (oldMember, newMember) => {
// Roles
const oldRoles = oldMember.roles.cache,
newRoles = newMember.roles.cache;
// Has Role?
const oldHas = oldRoles.has('role-id'),
newHas = newRoles.has('role-id');
// Check if removed or added
if (oldHas && !newHas) {
// Role has been removed
} else if (!oldHas && newHas) {
// Role has been added
}
});
https://discord.js.org/#/docs/main/stable/class/Client?scrollTo=e-guildMemberUpdate
This is simple with Client#guildMemberUpdate. Here’s some simple code that may help you
(This is the shortest code I could come up with)
client.on('guildMemberUpdate', async (oldMember, newMember) => {
if(oldMember.roles.cache.has('patreonRoleId')) return;
if(newMember.roles.cache.has('patreonRoleId')) {
//code here to run if member received role
//Warning: I didn’t test it as I had no time.
}
})
To see the removed role, just put the logical NOT operator (!) in front of both of the if statements like this:
if(!oldMember.roles.cache.has('patreonRoleId'))
if(!newMember.roles.cache.has('patreonRoleId'))
Note: make sure you have guildMembers intent enabled from the developers portal
This is one of my very first attempts (besides Purge time I made before)
I want to play an mp3 file until I ask Alexa to stop. This is was I have so far (The same code I used for the Purge one)
const Alexa = require('ask-sdk-core');
const Util = require('./util.js');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
},
handle(handlerInput) {
const audioUrl = Util.getS3PreSignedUrl("Media/white_noise_500_hz_formatted.mp3").replace(/&/g,'&');
return handlerInput.responseBuilder
.speak(`<audio src="${audioUrl}"/>`)
.getResponse();
}
};
exports.handler = Alexa.SkillBuilders.custom().addRequestHandlers(LaunchRequestHandler).lambda();
As a complete noob, I'm a bit lost. I'd need to wait to put the MP3 in a queue before it finishes or something.
Any idea is welcome, thanks!
PS. I know there are skills for white noise and rain sounds and so on, this one if for learning purposes :D
Where you're using it as a speak item, you're limited to 240 seconds and have to send the whole thing.
You want the audio player directive. https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html
I have created a skill with name "BuyDog" and its invocation name is "dog app"
So that should mean, I can use the intents defined inside only after the invocation name is heard. (is that correct?)
Then I have defined the Intents with slots as:
"what is {dog} price."
"Tell me the price of {dog}."
where the slot {dog} is of slot type "DogType". I have marked this slot as required to fulfill
Then I have added the endpoint to AWS lambda function where I have used the blueprint code of factskills project in node.js, and done few minor changes just to see the working.
const GET_DOG_PRICE_MESSAGE = "Here's your pricing: ";
const data = [
'You need to pay $2000.',
'You need to pay Rs2000.',
'You need to pay $5000.',
'You need to pay INR 3000.',
];
const handlers = {
//some handlers.......................
'DogIntent': function () {
const factArr = data;
const factIndex = Math.floor(Math.random() * factArr.length);
const randomFact = factArr[factIndex];
const speechOutput = GET_DOG_PRICE_MESSAGE + randomFact;
}
//some handlers.......................
};
As per the about code I was expecting when
I say: "Alexa open dog app"
It should just be ready to listen to the intent "what is {dog} price." and the other one. Instead it says a random string from the node.js code's data[] array. I was expecting this response after the Intent was spoken as the slot was required for intent to complete.
And when
I say: "open the dog app and Tell me the price of XXXX."
It asks for "which breed" (that is my defined question) But it just works fine and show the pricing
Alexa says: "Here's your pricing: You need to pay $5000."
(or other value from the data array) for any XXXX (i.e. dog or not dog type).
Why is alexa not confirming the word is in slot set or not?
And when
I say: "open the dog bark".
I expected alexa to not understand the question but it gave me a fact about barking. WHY? How did that happen?
Does alexa have a default set of skills? like search google/amazon etc...
I am so confused. Please help me understand what is going on?
Without having your full code to see exactly what is happening and provide code answers, I hope just an explanation for your problems/questions will point you in the right direction.
1. Launching Skill
I say: "Alexa open dog app"
It should just be ready to listen to the intent...
You are expecting Alexa to just listen, but actually, Alexa opens your skill and is expecting you to have a generic welcome response at this point. Alexa will send a Launch Request to your Lambda. This is different from an IntentRequest and so you can determine this by checking request.type. Usually found with:
this.event.request.type === 'LaunchRequest'
I suggest you add some logging to your Lambda, and use CloudWatch to see the incoming request from Alexa:
console.log("ALEXA REQUEST= " + event)
2. Slot Value Recognition
I say: "open the dog app and Tell me the price of XXXX."
Why is alexa not confirming the word is in slot set or not?
Alexa does not limit a slot to the slot values set in the slotType. The values you give the slotType are used as a guide, but other values are also accepted.
It is up to you, in your Lambda Function, to validate those slot values to make sure they are set to a value you accept. There are many ways to do this, so just start by detecting what the slot has been filled with. Usually found with:
this.event.request.intent.slots.{slotName}.value;
If you choose to set up synonyms in the slotType, then Alexa will also provide her recommended slot value resolutions. For example you could inlcude "Rotty" as a synonym for "Rottweiler", and Alexa will fill the slot with "Rotty" but also suggest you to resolve that to "Rottweiler".
var resolutionsArray = this.event.request.intent.slots.{slotName}.resolutions.resolutionsPerAuthority;
Again, use console.log and CloudWatch to view the slot values that Alexa accepts and fills.
3. Purposefully Fail to Launch Skill
I say: "open the dog bark".
I expected alexa to not understand the question but it gave me a fact about barking.
You must be doing this outside of your Skill, where Alexa will take any inputs and try to recognize an enabled skill, or handle with her best guess of default abilities.
Alexa does have default built-in abilities (not skills really) to answer general questions, and just be fun and friendly. You can see what she can do on her own here: Alexa - Things To Try
So my guess is, Alexa figured you were asking something about dog barks, and so provided an answer. You can try to ask her "What is a dog bark" and see if she responds with the exact same as "open the dog bark", just to confirm these suspicions.
To really understand developing an Alexa skill you should spend the time to get very familiar with this documentation:
Alexa Request and Response JSON Formats
You didn't post a lot of your code so it's hard to tell exactly what you meant but usually to handle incomplete events you can have an incomplete even handler like this:
const IncompleteDogsIntentHandler = {
// Occurs when the required slots are not filled
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'DogIntent'
&& handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED'
},
async handle(handlerInput) {
return handlerInput.responseBuilder
.addDelegateDirective(handlerInput.requestEnvelope.request.intent)
.getResponse();
}
you add this handler right above your actual handler usually in the index.js file of your lambda
This might not fix all your issues, but it will help you handle the event when a user doesn't mention a dog.
The skill's help prompt does not keep the skill session open.
How to solve this issue while publishing an Alexa skill?
Its not an issue but this is how it meant to work.
If alexa had allowed to keep the session opened for unlimited time, it would lead to misuse as people will keep session open always to listen what users are saying without their attention.
However, you have total of 16 seconds to get the input from user.
In your alexa response, if you set shouldEndSession as false then alexa will listen to get user input for 8 seconds.
If in addition to shouldEndSession you specified reprompt, then it reprompt the user the given string and again wait for 8 seconds.
So, you have 16 seconds in total.
You should set shouldEndSession to false. I do it as follows:
var handlers = {
// ...
'AMAZON.HelpIntent': function () {
this.emit(':tell', "Help message.");
this.response.shouldEndSession = false;
}
};
exports.handler = function(event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.appId = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};