What I Did

After waiting for over a month, I finally received my Amazon Echo and tried greeting on Twitter using it.

Although it might be possible to do this without creating a skill by using IFTTT, my goal was to actually build a custom skill, so I decided to implement it from scratch.

Most tutorials and samples use Node.js for Lambda methods, but since I love C#, I wrote it in C#.

Environment

Here are the required environments for implementation: Since C# uses .NET Core 1.0, I think development is possible even on Mac. I used Visual Studio 2017 (Windows version), but it seems AWS Toolkit supports versions earlier than 2017 as well.

Implementation of Alexa Skill

I followed this tutorial almost exactly. (By the way, this tutorial was in Japanese and very easy to understand.)

You need to register for an Amazon Developer account beforehand.

This time, I did not use the Skill Builder.

Skill Name & Invocation Name

Both are set to “Twitter” (pronounced as “Tsuittā”).

Intent Schema

I defined an intent called TwitterIntent, with a slot named Word of type GREETING_WORD.

{
  "intents": [
    {
      "slots": [
        {
          "name": "Word",
          "type": "GREETING_WORD"
        }
      ],
      "intent": "TwitterIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    }
  ]
}

Custom Slot Type

The slot will contain greeting words. It seemed that there was no suitable default slot type, so I created a custom slot.

Type: GREETING_WORD

Values: Good morning Hello Good night Good evening Hey Hey (casual) Hi

Sample Utterances

Ideally, you would register more patterns, but for now, I registered the following five:

TwitterIntent {Word} o-tsubuyai-te (say on Twitter) TwitterIntent {Word} tte tsubuyai-te (say on Twitter) TwitterIntent {Word} tte yatte (do it) TwitterIntent {Word} te itte (say it) TwitterIntent {Word} shite (do it)

Lambda Function Implementation (C#)

Register your AWS account in advance so you can use Lambda functions.

Installing AWS Toolkit for Visual Studio

Download and install it from the AWS website. With this, you can implement, publish, and test your function all within Visual Studio, making things much easier.

After installation, when you launch Visual Studio, a window will appear prompting you to enter your AWS user information. Enter it as needed.

Creating a Project for Lambda

When creating the project, select “AWS Lambda Project (.NET Core)”. For the function type, I chose Empty Function. 2_projecttemplate.PNG

Adding Libraries

I added the following two libraries:

  • Alexa.Net
  • CoreTweet

Function Implementation

I opened Function.cs and implemented it as follows.

TwitterAPI Information

I was going to hard code it for confirmation, but I thought I could use the environment variable function of Lambda, so I used it. *Note: I was not very familiar with Lambda, so if you find anything wrong, please let me know.

   private string APIKey;
   private string APISecret;
   private string AccessToken;
   private string AccessTokenSecret;
        
   public Function()
   {
       APIKey = Environment.GetEnvironmentVariable("API_KEY");
       APISecret = Environment.GetEnvironmentVariable("API_KEY_SECRET");
       AccessToken = Environment.GetEnvironmentVariable("ACCESS_TOKEN");
       AccessTokenSecret = Environment.GetEnvironmentVariable("ACCESS_TOKEN_SECRET");
   }

Request Sorting

I implemented it to ignore all requests other than TwitterIntent.

   // Get request type
   var requestType = input.GetRequestType();

   // Ignore requests other than IntentRequest
   if (requestType != typeof(IntentRequest)) return null;

   var intentRequest = input.Request as IntentRequest;

   // Ignore intents other than TwitterIntent
   if (!intentRequest.Intent.Name.Equals("TwitterIntent")) return null;

Response Implementation

I extracted the greeting words from the request and tweeted them to Twitter, then told Alexa that I had tweeted them.

   // Get the value of the Word slot
    var wordSlotValue = intentRequest.Intent.Slots["Word"].Value;

   // Generate necessary information for Twitter API
   var tokens = CoreTweet.Tokens.Create($"{APIKey}", $"{APISecret}", $"{AccessToken}", $"{AccessTokenSecret}");

   // Execute tweet
   tokens.Statuses.UpdateAsync(new { status = wordSlotValue }).Wait();

   // Response from Alexa
   return ResponseBuilder.Tell($"<speak>I tweeted {wordSlotValue}</speak>");
```;
```


### Function.cs

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Amazon.Lambda.Core;
using Alexa.NET;
using Alexa.NET.Request;
using Alexa.NET.Response;
using Alexa.NET.Request.Type;

// Assembly attribute to enable the Lambda function&#39;s JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace AlexaToTwitter
{
    public class Function
    {
        private readonly string APIKey;
        private readonly string APISecret;
        private readonly string AccessToken;
        private readonly string AccessTokenSecret;

        public Function()
        {
            APIKey = Environment.GetEnvironmentVariable("API_KEY");
            APISecret = Environment.GetEnvironmentVariable("API_KEY_SECRET");
            AccessToken = Environment.GetEnvironmentVariable("ACCESS_TOKEN");
            AccessTokenSecret = Environment.GetEnvironmentVariable("ACCESS_TOKEN_SECRET");
        }

        public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext context)
        {
            // Get request type
            var requestType = input.GetRequestType();

            // Ignore requests other than IntentRequest
            if (requestType != typeof(IntentRequest)) return null;

            var intentRequest = input.Request as IntentRequest;

            // Ignore intents other than TwitterIntent
            if (!intentRequest.Intent.Name.Equals("TwitterIntent")) return null;

            // Get the value of the Word slot
            var wordSlotValue = intentRequest.Intent.Slots["Word"].Value;

            // Generate necessary information for Twitter API
            var tokens = CoreTweet.Tokens.Create($"{APIKey}", $"{APISecret}", $"{AccessToken}", $"{AccessTokenSecret}");

            // Execute tweet
            tokens.Statuses.UpdateAsync(new { status = wordSlotValue }).Wait();

            // Response from Alexa
            return ResponseBuilder.Tell($"I tweeted {wordSlotValue}");
        }
    }
}

```


### Update Lambda

Right-click on the project and click "Publish to AWS Lambda...".

Select the Function Name and Role, and upload.
You can also set environment variable values and test the function after publishing.

If there are no problems, add "Alexa Skills Kit" as a trigger from the AWS Web.
(Since I couldn't add the trigger directly from Visual Studio, I did it via the AWS Web console, which I thought might be more interesting anyway.)
<img width="1009" alt="3_skillkit.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/119290/d34522b9-9136-d6b1-8cf2-1ae826f8a348.png"/>

# Testing on Real Device

After connecting the Lambda function in the Alexa skill settings on Amazon Developer, fill in the required details and enable the skill for your own Amazon account using Skills Beta Testing.

Then, nervously, I said to Echo:
"Alexa, tweet 'Good morning' on Twitter."
And it was properly reflected on Twitter.

Even if you change the "Good morning" part to other words, it recognizes them most of the time.
It could even recognize words not defined in the list.

# Summary

I wanted to make some kind of skill using Amazon Echo, so I tried implementing it with C#, which I'm familiar with.

Thanks to AWS Toolkit for Visual Studio and Alexa.Net, I could code without worrying much about Lambda or Alexa itself, so it was less difficult than I expected.

Alexa's recognition rate is also pretty good. I once tried automating daily life with Amazon Dash Button, but with Alexa, I feel like I can do even more depending on the ideas I come up with.