alexa / alexa-skills-kit-sdk-for-nodejs

The Alexa Skills Kit SDK for Node.js helps you get a skill up and running quickly, letting you focus on skill logic instead of boilerplate code.
Apache License 2.0
3.13k stars 738 forks source link

how to prevent an intent trigger if another intent has not been called first. #584

Closed anthowm closed 5 years ago

anthowm commented 5 years ago

I'm submitting a...

[ ] Regression (a behavior that used to work and stopped working in a new release) [ ] Bug report [ ] Performance issue [ ] Feature request [ ] Documentation issue or request [X ] Other... Please describe: how to avoid my skill to trigger WaitAnswerIntentHandler if RandomLetterIntentHandler does not activate first.


let gameState = 0;
const RandomLetterIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'RandomLetterIntent';
    },
    handle(handlerInput) {
  // **get a letter from the user**
        const requestAttributes = handlerInput.attributesManager.getRequestAttributes();
        const randomLetter = randomLetterGenerator.getOneRandomLetter();
        const speechText = requestAttributes.t('RANDOM_LETTER_ASK', randomLetter);
        timerUtils.startTimer();
        puntuacion = 0;
        letter= randomLetter;
        gameState = 1;
        return handlerInput.responseBuilder
            .speak(speechText)
            .reprompt(speechText)
            .getResponse();
    }
};
const WaitAnswerIntentHandler = {
    canHandle(handlerInput){
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
        && Alexa.getIntentName(handlerInput.requestEnvelope) === 'WaitAnswerIntent'
        && gameState > 0;
    },
    handle(handlerInput){
### **// get {animal}{country}{color}{food} (not all required and can be in any order) but need the letter that is obtained in the previous intent**
        const intent = handlerInput.requestEnvelope.request.intent;

        const animal = intent.slots.ANIMAL.value;
        const country = intent.slots.COUNTRY.value;
        const color = intent.slots.COLOR.value;
        const food = intent.slots.FOOD.value;

        let cadenaFinal = '';
        let tiempoFinal = 0;

        if(animal && animal[0]===letter){
            puntuacion = puntuacion + 10;
            cadenaFinal = cadenaFinal + ' ' + animal;
        }
        if(country && country[0]===letter){
            puntuacion = puntuacion + 10;
            cadenaFinal = cadenaFinal + ' ' + country;
        }
        if(color && color[0]===letter){
            puntuacion = puntuacion + 10;
            cadenaFinal = cadenaFinal + ' ' + color;
        }
        if(food && food[0]===letter){
            puntuacion = puntuacion + 10;
            cadenaFinal = cadenaFinal + ' ' + food;
        }

        tiempoFinal = timerUtils.endTimer();
        puntuacion = puntuacion - tiempoFinal;

        if(!cadenaFinal){cadenaFinal='ninguna'}
        const repromtText = 'pídeme otra letra para seguir jugando';
        const speakOutput = `Tu respuesta válida fue ${cadenaFinal}, has tardado ${tiempoFinal.toString()} segundos y tu puntuación es ${puntuacion.toString()}`;
        gameState = 0;
        return handlerInput.responseBuilder
        .speak(speakOutput)
        .reprompt(repromtText)
        .getResponse();
    }
};
ShenChen93 commented 5 years ago

Hi @anthowm

Thanks for using our SDK. For the issue you post, I want to confrim your use case first. I see you have two intentHandler A and B, and you don't want to trigger B when A is not activated before. Then the solution depends on your expected behavior of the skill.

First, to detect whether intent A is triggered before, you can maintain a global variable or use our AttributeManager to record whether this intent handler has been triggered or not.

However, if your use case is let service side never send Intent B request to skill until Intent A is activated. Our SDK side cannot support that.

Please let me know if it helps.

Thanks, Shen

anthowm commented 5 years ago

@ShenChen-Amazon Hi thanks for ur reply, I take your first approach so I create a gameState as global var to handle it and it works but always trigger IntentReflectorHandler. How I return errorHandler can you share me the docs or an example. thanks !

ShenChen93 commented 5 years ago

Hi @anthowm,

The IntentReflectorHandler is used for interaction model testing and debugging. I don't know how you defined it, but I guess the canHandle function looks like this:

canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest';
},

Therefore, it can means this handler can handle all IntentRequest and thus the incoming request can always find a handler to handle it. No error handler will be triggered as the request is well handled.

For your use case, I don't think its good to handle this situation in an error handler. I create a very simple sample so you can reference.

Thanks, Shen

anthowm commented 5 years ago

Hi @ShenChen-Amazon Your example works for my project. Thanks, Shen !