Cake Time:

Construa uma Skill engajadora

Adicionando memória à sua skill

Nesta seção, você habilitará a skill Cake Time para lembrar o aniversário do usuário. Qual é o ponto da skill coletar informações se não se lembrar das mesmas?

Use o Console do Portal dos Desenvolvedores de Alexa para este módulo. Faça login no console e abra a skill Cake Time.

Passo 1: use o Amazon S3 para salvar e ler dados

No momento, você tem o dia, o mês e o ano do aniversário do usuário dentro do código. O problema é que a skill esquece esses valores quando o código termina a execução. Para resolver o problema, salve os valores no Amazon S3. Dessa forma, a skill pode lê-los de sessão para sessão.

O SDK fornece um mecanismo útil para salvar informações entre as sessões: o AttributesManager. Com o manager, seu código de leitura/gravação pode permanecer o mesmo, mesmo se você alterar onde salvará seus dados posteriormente.

O código de back-end para as skills de Alexa podem estar em qualquer servidor HTTPS. Na maioria das vezes, os desenvolvedores de Alexa escrevem e hospedam seu código de back-end usando a AWS. Ao criar a Cake Time, você escreveu código no Console do Portal dos Desenvolvedores usando uma skill hospedada pela Alexa. Esse código está sendo executado no nível gratuito da AWS, que tem limitações. As skills hospedadas na Alexa são ótimas para aprender a criar e até publicar skills simples antes que você tenha um grande público. No entanto, se sua skill se tornar popular, convém transferir seu código de back-end para seus próprios recursos da AWS.

Como isso se relaciona com a adição de memória à sua skill? Ao usar uma skill hospedada pela Alexa para o seu código de back-end, ela será armazenada no Amazon S3. Se você optar por criar seu código com seus próprios recursos da AWS, poderá fazer mais sentido usar o Amazon DynamoDB. Não se preocupe se você não souber a diferença entre os dois. O importante é saber que o código de back-end que você está escrevendo agora funcionará com o Amazon S3 e exigirá apenas pequenas alterações para trabalhar com o DynamoDB se você decidir migrar para seus próprios recursos da AWS posteriormente.

Comece usando o AttributesManager para salvar o aniversário do usuário na Cake Time.

a. No Console do Portal dos Desenvolvedores, clique na guia Code (Código).

b. Clique duas vezes no arquivo package.json no painel à esquerda. O arquivo será aberto no editor.

c. Observe que o "nome" na linha 2 é "hello-world". Mude o mesmo para "cake-time".

code nav link screenshot

Encontre a seção “dependencies” (dependências). Você vai adicionar uma dependência. É mais fácil colocar uma nova dependência no final da lista existente.

d. Encontre a linha que começa com "aws-sdk". Crie uma nova linha abaixo dela, copie e cole o seguinte código:

"ask-sdk-s3-persistence-adapter": "^2.0.0"

Nota: Ao adicionar a nova dependência, você deve adicionar uma vírgula (,) ao final da linha anterior (que começa com "aws-sdk"), como mostra o exemplo.

dependency screenshot

O arquivo package.json deve se parecer com o seguinte agora:

package.json screenshot

e. Clique em Save (Salvar).

save button

f. Volte para o outro arquivo clicando na guia index.js.

A nova dependência permite que você use o AttributesManager para salvar e ler dados do usuário usando o Amazon S3. Agora, você precisa importar essa dependência para o código. Para fazer isso, você precisa informar ao código de que a dependência existe.

g. No arquivo index.js, encontre a linha que começa com const Alexa. Crie uma nova linha logo abaixo e copie e cole o seguinte código:

const persistenceAdapter = require('ask-sdk-s3-persistence-adapter');

O código deve estar assim agora:

code snippet

h. Role para baixo no código até encontrar a linha que inicia com export.handler. Crie uma nova linha logo abaixo e copie e cole o seguinte código:

.withPersistenceAdapter(
new persistenceAdapter.S3PersistenceAdapter({bucketName:process.env.S3_PERSISTENCE_BUCKET})
)

Uma vez adicionado, o código fica assim:

code snippet

i. Clique em Save (Salvar).

save button

Agora você está pronto para usar o AttributesManager para salvar e ler dados no Amazon S3. Mais tarde, se você decidir mover o código de back-end da sua skill para seus próprios recursos da AWS, você reverterá as alterações feitas nesta etapa.

Passo 2: criar código assíncrono

Agora você modificará o código para salvar o aniversário do usuário. Na guia Code (Código), no arquivo index.js, localize o CaptureBirthdayIntentHandler. Este é o handler que você criou na última seção. Antes de fazer alterações, vamos revisar o conceito de código assíncrono. Se você estiver familiarizado, fique à vontade para pular adiante.

Quando o código é executado, normalmente é executado muito rápido, linha por linha. Isto é fantástico. Um computador pode fazer muitos cálculos e fazê-los muito mais rapidamente do que um ser humano. No entanto, quando uma parte do código precisa fazer algo que leva tempo antes de passar para a próxima linha, a operação pode ser interrompida. Seria melhor se a parte do código que leva tempo pudesse ser iniciada e executada sem interromper o restante do código. Isso é chamado de código assíncrono. A razão pela qual é importante aqui é que salvar e ler dados do usuário leva um pouco mais de tempo para ser executado do que o restante do código da skill. Felizmente, tornar um bloco de código assíncrono é bastante simples.

a. Encontre a CaptureBirthdayIntentHandler. Há uma função canHandle () e uma função handle (). Na frente da função handle (), digite async seguido por um espaço.

async handle(handlerInput) {

O código agora fica assim:

code snippet

b. Em seguida, você usará o AttributesManager para salvar o aniversário do usuário. Dentro do CaptureBirthdayIntentHandler, na função handle (), encontre a linha que começa com const day. Crie uma nova linha logo abaixo e copie e cole o seguinte código:

const attributesManager = handlerInput.attributesManager;

O código da skill Cake Time recebe o ano, mês e dia. Você precisa informar ao Amazon S3 para salvar esses valores. O código informa ao AttributesManager quais são os dados e o manager os envia ao Amazon S3.

c. No CaptureBirthdayIntentHandler, localize a linha que você acabou de adicionar (ela começa com const attributeManager). Crie uma nova linha logo abaixo e copie e cole o seguinte código:

const birthdayAttributes = {
"year" : year,
"month" : month,
"day" : day
};

Este trecho de código está mapeando as variáveis já declaradas no código para as variáveis correspondentes que serão criadas no Amazon S3 quando o código for executado.

Essas variáveis agora são declaradas como persistentes (elas são locais para a função na qual são declaradas, ainda que seus valores sejam retidos na memória entre as chamadas para a função). Agora você pode salvar os dados do usuário para eles. Primeiro, use o AttributesManager para definir os dados para salvar no Amazon S3.

Essa seção do código deve ficar como a ilustração abaixo:

code snippet

d. Dentro do CaptureBirthdayIntentHandler, na função handle (), encontre a linha que começa const speechText. Crie uma nova linha logo acima dela. Copie e cole o seguinte código:

attributesManager.setPersistentAttributes(birthdayAttributes);

Lembra de ter adicionado a palavra-chave async no início de uma linha um tempo atrás? Agora, adicione uma linha de código que demore um pouco para ser executada, pois as informações do usuário são enviadas ao Amazon S3. Esta linha tem a palavra-chave await no início.

e. Dentro do CaptureBirthdayIntentHandler, na função handle (), encontre a linha que inicia com attributesManager.setPersistentAttributes. Crie uma nova linha logo abaixo dela. Copie e cole o seguinte código:

await attributesManager.savePersistentAttributes();

O código agora deve ficar assim:

code snippet

A palavra-chave "await" informa ao código para pausar e continuar após as informações do usuário serem salvas no Amazon S3. Se você não incluir a palavra-chave, o código continuará sendo executado, independentemente de os dados serem salvos no Amazon S3 com êxito ou não. Isso pode resultar na falta de salvamento dos dados e na Alexa solicitar o aniversário do usuário sempre que iniciar a skill.

f. Clique Save (Salvar).

save button

Passo 3: ler dados armazenados

Ótimo, agora o aniversário do usuário está salvo no Amazon S3. No entanto, agora a skill precisa ser atualizada para que na próxima vez que o usuário abra a Cake Time, a Alexa saiba que as informações de aniversário do usuário estão armazenadas e ela não precisa pedir. Para fazer isso, você modificará o código para ler os dados armazenados no Amazon S3 antes de solicitar o aniversário do usuário. Se os dados existirem, a Alexa não precisará solicitá-los. Se os dados não estiverem disponíveis, a Alexa solicitará as informações.

Um bucket do Amazon S3 é um recurso de armazenamento em nuvem pública. Um bucket é semelhante a uma pasta de arquivo para armazenar objetos, que consiste em dados e metadados descritivos.

É necessário um novo handler para ler os dados armazenados. As funções canHandle () e handle () no novo handler se comunicarão com o Amazon S3. No entanto, as funções estariam fazendo a mesma coisa, o que é um desperdício. Para consolidar, use um interceptador. O interceptador intercepta a solicitação para ler as informações de aniversário armazenadas no Amazon S3.

a. Encontre o comentário no código que começa com // TheSkillBuilder acts as an entry point. Crie uma nova linha logo acima deste comentário. Copie e cole o seguinte código:

const LoadBirthdayInterceptor = {
    async process(handlerInput) {
        const attributesManager = handlerInput.attributesManager;
        const sessionAttributes = await attributesManager.getPersistentAttributes() || {};

        const year = sessionAttributes.hasOwnProperty('year') ? sessionAttributes.year : 0;
        const month = sessionAttributes.hasOwnProperty('month') ? sessionAttributes.month : 0;
        const day = sessionAttributes.hasOwnProperty('day') ? sessionAttributes.day : 0;

        if (year && month && day) {
            attributesManager.setSessionAttributes(sessionAttributes);
        }
    }
};

Essa seção do código agora deve parecer com a ilustração abaixo:

code snippet

Agora adicione um pedaço de código que registra o interceptador para que o SDK saiba que ele existe.

b. Na seção export.handler, na parte inferior do código, localize a linha que começa com IntentReflectorHandler) // make sure. Crie uma nova linha logo abaixo dela. Copie e cole o seguinte código:

.addRequestInterceptors(
    LoadBirthdayInterceptor
)

Esssa parte do código agora deve ficar assim:

code snippet

Por fim, adicione o novo handler. Você o adicionará entre o LaunchRequestHandler e o CaptureBirthdayIntentHandler.

c. Encontre a linha que começa com const CaptureBirthdayIntentHandler. Crie uma nova linha logo acima, e copie e cole o seguinte código para o novo handler:

const HasBirthdayLaunchRequestHandler = {
    canHandle(handlerInput) {

        const attributesManager = handlerInput.attributesManager;
        const sessionAttributes = attributesManager.getSessionAttributes() || {};

        const year = sessionAttributes.hasOwnProperty('year') ? sessionAttributes.year : 0;
        const month = sessionAttributes.hasOwnProperty('month') ? sessionAttributes.month : 0;
        const day = sessionAttributes.hasOwnProperty('day') ? sessionAttributes.day : 0;

        return handlerInput.requestEnvelope.request.type === 'LaunchRequest' && year && month && day;

    },
    handle(handlerInput) {

        const attributesManager = handlerInput.attributesManager;
        const sessionAttributes = attributesManager.getSessionAttributes() || {};

        const year = sessionAttributes.hasOwnProperty('year') ? sessionAttributes.year : 0;
        const month = sessionAttributes.hasOwnProperty('month') ? sessionAttributes.month : 0;
        const day = sessionAttributes.hasOwnProperty('day') ? sessionAttributes.day : 0;

        // TODO:: Use the settings API to get current date and then compute how many days until user's birthday
        // TODO:: Say Happy birthday on the user's birthday

        const speakOutput = `Welcome back. It looks like there are X more days until your y-th birthday.`;

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .getResponse();
    }
};

O novo handler possui as funções canHandle () e handle (). A função canHandle () verifica se as informações de aniversário do usuário estão salvas no Amazon S3. Se estiverem, o handler informa ao SDK que ele pode fazer seu trabalho (possui as informações de aniversário do usuário e pode seguir). A função handle () diz a Alexa para dizer "Bem-vindo de volta. Parece que há X mais dias até o seu aniversário de X anos".

Quando você alterou o nome de um handler em uma seção anterior, também teve que alterar o nome na lista de handlers na parte inferior do código. Como você adicionou um novo handler, você deve adicionar o novo handler também a esta lista.

d. Na parte inferior do código, localize a função .addRequestHandlers () e a linha que inicia com LaunchRequestHandler. Crie uma nova linha logo acima dela. Copie e cole o seguinte código na nova linha:

HasBirthdayLaunchRequestHandler,

Essa parte do código agora fica assim:

code snippet

e. Clique em Save (Salvar)

save button

f. Clique em Deploy (Implementar).

save button

Como excluir ou redefinir o aniversário do usuário

Ao testar, pode ser necessário excluir ou redefinir o aniversário do usuário. Existem duas maneiras de fazer isso.

Use o primeiro método no simulador na guia Test (Teste) do console do portal. Digite ou diga: "Alexa, diga a Cake Time que nasci em {mês} {dia} {ano}".

O segundo método é excluir as informações salvas do Amazon S3, seguindo os seguintes passos:

a. Enquanto estiver na guia Code (Código), clique em Media Storage no canto inferior esquerdo da tela. O S3 Management Console abrirá.

media storage screenshots

b. No topo da página, encontre as trilhas de navegação. Clique na trilha de navegação que inicia com amzn-1-ask-skill.

breadcrumb screenshot

c. Clique na caixa de seleção ao lado do(s) arquivo(s) que começa(m) com amzn1.ask.account.

breadcrumb screenshot

d. Clique em Actions (Ações).

e. Clique em Delete (Excluir). O aniversário do usuário será excluido.

Resumo

Aqui está um resumo do que você fez nesta seção. Primeiro, você ajustou a skill Cake Time para usar o AttributesManager para salvar e ler as informações do usuário no Amazon S3. Em seguida, você adicionou o código ao CaptureBirthdayIntentHandler para salvar o aniversário do usuário. Por fim, você criou um novo handler (HasBirthdayLaunchRequestHandler) para que a Alexa não solicite repetidamente o aniversário do mesmo usuário.

É hora de testar, clique na guia Test (Teste) e siga as etapas abaixo:

Etapa 1: inicie a skill

Diga "Abra Cake Time".

Alexa deve responder: "Olá! Bem-vindo a Cake Time. Quando é seu aniversário?"

Diga a Alexa seu aniversário

Sinta-se à vontade para tentar fornecer informações parciais à Alexa e garantir que ela solicite e colete as informações ausentes.

Quando ela tiver seu mês, dia e ano de nascimento, Alexa deverá responder: "Obrigado, lembrarei que seu aniversário é {mês} {dia} {ano}".

A sessão termina. Nesse momento, sem o código que você adicionou nesta seção, na próxima vez que você invocar a skill, a Alexa solicitará seu aniversário novamente. Agora, a Alexa armazena essas informações.

Abrir a skill uma segunda vez

Diga "Abra Cake Time". Alexa deve responder: “Bem-vindo de volta. Parece que há mais X dias até o seu aniversário de X anos. ”

Você provavelmente percebeu que, com a maneira como o código está no momento, a Alexa está dizendo "X" e "X". Não se preocupe. Na próxima seção, você trabalhará no código para calcular quantos dias até o próximo aniversário do usuário para que a Alexa possa responder com essas informações.

Código

Se sua skill não está funcionando ou você está recebendo algum tipo de erro de sintaxe, baixe o seguinte exemplo de código de trabalho. Vá para a guia Code (Código) no Console do Portal dos Desenvolvedores de Alexa e copie e cole o código no arquivo index.js. Certifique-se de salvar e implantar o código antes de testá-lo.