In this article, we will walk through to how to add, remove, and list Objects in your Cosmic JS Bucket with an Alexa Skill via voice commands. The skill we will use in this tutorial is a Chore / Task Tracker that allows you to say thing like “Alexa, tell chore tracker to add mowing the lawn”, “Alexa, ask chore tracker to list off my chores”, and “Alexa, tell chore tracker to remove mowing the lawn”. We will be Utilizing a custom Cosmic JS Bucket to store these Chores.
- Amazon AWS Account
- Amazon Developer Account
- Node >= v4.5
Install ASK CLI
First, we are going to need to install the ASK CLI. This tool will allow us to easily deploy our skill to our Developer Portal and AWS Lambda Instance in the future for testing.
Note: The AWS Configuration is based on @rajeeva's fantastic Medium Article, so make sure to check him out.
Create CLI Policy in AWS IAM
We are going to need a user that has full access to our AWS account in order to deploy our Skill from the command line easily. To do this, go to the IAM tab in your AWS Console, navigate to Policies, and select Create Policy.
You can name this policy anything, but I am going to stick with AWS_CLI_FULL_ACCESS. Next, we want to add the actual policy contents, and you can copy the following JSON for the policy configuration.
After this, follow the prompts and press Create Policy. If all is well, you should get this alert.
Create CLI User in AWS IAM
Now that we have created a new policy, we need to attach that policy to a user. Go back to the IAM tab in the AWS Console, navigate to Users, and select Add User.
Note: I already have a user named AWS_CLI_FULL_ACCESS, but you should not.
Next, name the user by following the prompts. You can name it whatever you want, but I am going to stick with AWS_CLI_FULL_ACCESS. Make sure to select Programmatic Access when prompted for the Access Type.
It is going to ask to attach a policy to the user and make sure to select the AWS_CLI_FULL_ACCESS policy we created earlier.
Now follow the prompts until it displays the user and their Access Key ID and Secret Key. These are VERY important and we will need them for the next step, so make sure to write these down somewhere.
Adding our IAM User to our local machine
With our IAM User now created, we need to add him to our AWS Local Config. This is located at different locations depending on your OS.
- macOS: ~/.aws/credentials
- Windows: %USERPROFILE%\.aws\credentials.txt
We want to add our AWS IAM User to this file. Add the following lines and save the file.
Initializing the ASK Profile
We need to configure an ASK profile with our IAM User. To do this, we need to run the following command.
You will be prompted to log in with your Amazon Account, and if you are authenticated it will let you know that the profile is initialized successfully.
Deploying the Skill
Navigate to the Project, and run the following command.
If you get the following error: [Error]: Cannot resolve profile [default], go into the config file located at ~/.ask/cli_config and change [default] to [AWS_CLI_FULL_ACCESS].
And just like that, your skill is deployed with a corresponding AWS Lambda Instance and Skill. You can now test the skill by navigating to the Alexa Skill Kit page on the Amazon Developer website. From there, you can test the skill by clicking on the Test section.
Make sure to re-deploy the skill every time when you want to test new features!
Our API File
There currently is not any file for us to put our API calls to Cosmic JS in. So, let's make one. Go ahead and create a file named api.js in the lambda/custom directory. Let's first add some basic Cosmic JS setup.
This is pretty straightforward. The first two parts are basic require statements, one for the Cosmic JS npm module, and the second one is for our config.js file in order for us to access our Bucket Slug and API Keys. We then create a reference to our Chore Bucket for later use.
Reading Objects from our Bucket
Now we want to add a function for retrieving all of our Chores added to the Bucket, that way our Alexa Skill can list them off to the user when they want to retrieve them.
First, let's update our api.js file
This is a simple function that will return all objects from the Chore Bucket that we previously created a reference to before. As getObjects() returns a Promise, we handle it with the traditional then() and catch(). Lastly, we map over all of the Chores in choreData, and add the titles to an array and return it.
We will also need to update our ListChoresIntentHandler in index.js to call getChores() in our API file.
Make sure to include api.js at the to top of index.js with a require() statement. Also, keep in mind that we added the async modifier to handle(). This has to be added in order to allow us to use the await keyword.
Now, when you ask Alexa "Ask chore tracker to list off my chores?", it should say back "Your chores are mowing the lawn."
Writing Objects to our Bucket
Now that we have a way of retrieving all of our chores added, let's add a function that allows us to add a new Chore.
First, let's update our api.js file with the following function.
This is a simple function that will add an Object of Object Type Chore to our Chore Bucket. Similar to the getObjects(), we handle the Promise with then() and catch(). Lastly, we return a boolean value whether the response is not null, indicating a successful action.
We will also need to update our AddChoreIntentHandler in index.js to call addChore().
This is a little longer than the last Handler since we have to retrieve the name of the Chore the user said by reading the choreSlot. Next, we call addChore() and check to see if it was a successful operation or not and return a corresponding message.
Now, when you ask Alexa "Ask chore tracker to add cleaning the dishes", it should say back "Added cleaning the dishes to your chores list", as well as adding a new Object to your Bucket.
Removing Objects from our Bucket
But, what if we want to remove chores? Like before, we will need to first add removeChore() to our api.js file and update the RemoveChoreIntentHandler in index.js.
First, let's update the api.js file for the last time.
This function is almost identical to addChore(), but we modify the params and call deleteObject() on our Chore Bucket instead. We also have to replace all spaces in the chore with hyphens as that is how Objects are stored in Buckets. This also returns a boolean value on whether the operation was successful or not.
Also update the RemoveChoreIntentHandler in index.js
This is also very similar to the AddChoreIntentHandler, but with different messages and a different API Call.
So, when you ask Alexa "Ask chore tracker to remove mowing the lawn", it should say back "Successfully removed mowing the lawn", as well as removing the corresponding Object from the Bucket.
There you go! You now have a working Alexa Skill that you can use to keep track of any chores or tasks you have to do around the house. Feel free to experiment with adding your own chores by modifying the en-US.json model file and responses by modifying the Messages.js file.
If you have any questions or run into any snags, feel free to open an issue on the Completed Source Code GitHub Repository and I'll be more than happy to respond :).