3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Qiitaの最新記事を教えてくれるアレクサスキルを作ろう Alexa X Lambda X Golang 

Last updated at Posted at 2024-03-29

1.はじめに

1.1目的

golangと、lambdaを使ってアレクサスキルと作りたくなったのでやってみる。

1.2環境

Windows(GitBash)
Go Version 1.22.0

1.3前提条件

  • Amazon 開発者アカウントの作成を事前に行う。下記リンクより、Amazon開発者アカウントの作成を元に準備してください

2.Golangでソースを書き、Lambdaにデプロイしよう

アプリ名naviQiita(ナビキータ)で作成をしていきます。
以下の解説でアプリ名やリソース名などは自身が作成するものに適宜合わせてください。

2.1 コーディング

公式ドキュメントを参考に作成してみる

  1. goプロジェクトの準備を行います
    適当な作業ディレクトリを作成しそのディレクトリ配下で下記コマンドを叩き、Go.modを作成しますmodule-pathは適宜自身の物に合わせてください(僕は、module-pathを"githun.com/keny-N/NaviQiita"にします)
    $ go mod init [module-path]
    go: creating new go.mod: module [module-path]
    
  2. AWS Lambda go ADKのインストール
    $ go get github.com/aws/aws-lambda-go/lambda
    go: downloading github.com/aws/aws-lambda-go v1.46.0
    go: added github.com/aws/aws-lambda-go v1.46.0
    
  3. ファイルを作成していく
  • /cmd/alexa-skill/main.go
main.go
package main

import (
	"context"

	"githun.com/keny-N/NaviQiita/internal/qiita"
	"githun.com/keny-N/NaviQiita/pkg/response"

	"github.com/aws/aws-lambda-go/lambda"
)

func Handler(ctx context.Context) (response.AlexaResponse, error) {
	items, err := qiita.FetchQiitaItems()
	if err != nil {
		return response.AlexaResponse{}, err
	}

	message := "最新のQiitaの記事を5つ紹介します。。: "
	for _, item := range items {
		message += item.Title + ", URL: " + item.URL + ". "
	}

	return response.CreateResponse(message), nil
}

func main() {
	lambda.Start(Handler)
}
  • /internal/qiita/qiita.go
qiita.go
package qiita

import (
	"encoding/json"
	"net/http"
)

type QiitaItem struct {
	Title string `json:"title"`
	URL   string `json:"url"`
}

func FetchQiitaItems() ([]QiitaItem, error) {
	resp, err := http.Get("https://qiita.com/api/v2/items?page=1&per_page=5")
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var items []QiitaItem
	if err := json.NewDecoder(resp.Body).Decode(&items); err != nil {
		return nil, err
	}

	return items, nil
}

  • /pkg/response/response.go
response.go
package response

type AlexaResponse struct {
	Version           string   `json:"version"`
	SessionAttributes struct{} `json:"sessionAttributes"`
	Response          struct {
		OutputSpeech struct {
			Type string `json:"type"`
			Text string `json:"text"`
		} `json:"outputSpeech"`
	} `json:"response"`
}

func CreateResponse(message string) AlexaResponse {
	return AlexaResponse{
		Version: "1.0",
		Response: struct {
			OutputSpeech struct {
				Type string `json:"type"`
				Text string `json:"text"`
			} `json:"outputSpeech"`
		}{
			OutputSpeech: struct {
				Type string `json:"type"`
				Text string `json:"text"`
			}{
				Type: "PlainText",
				Text: message,
			},
		},
	}
}

go.mod
module githun.com/keny-N/NaviQiita

go 1.22.0

require github.com/aws/aws-lambda-go v1.46.0 // indirect

go.sum
github.com/aws/aws-lambda-go v1.46.0 h1:UWVnvh2h2gecOlFhHQfIPQcD8pL/f7pVCutmFl+oXU8=
github.com/aws/aws-lambda-go v1.46.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=

4.以下のコマンドを実行して、Linux向けの実行可能ファイルをビルドします
"main"という名前の実行ファイルが生成されます

```
$ GOOS=linux GOARCH=amd64 go build -o bootstrap cmd/naviQiita/main.go  
```

5.mainファイルをzip形式に圧縮する
(注意)ここが一番ハマッタ
windows環境で圧縮する場合は、公式の手順通り行ってください。
WindowsでそのままZIPを作成したらパーミッションエラーで怒られます。

go install github.com/aws/aws-lambda-go/cmd/build-lambda-zip@latest
# このコマンドだけpowershellでたたきました(他はGitbash)
$ $env:GOOS = "linux"
$ $env:GOARCH = "arm64"
$ $env:CGO_ENABLED = "0"
$ go build -tags lambda.norpc -o bootstrap cmd\naviQiita\main.go
$ ~\Go\Bin\build-lambda-zip.exe -o myFunction.zip bootstrap

6.最終的なフォルダ構成
githubにソースコードを挙げているので参考にしてください

└─NaviQiita
    │  bootstrap
    │  go.mod
    │  go.sum
    │  myFunction.zip
    │
    ├─cmd
    │  └─naviQiita
    │          main.go
    │
    ├─internal
    │  └─qiita
    │          qiita.go
    │
    └─pkg
        └─response
                response.go

2.2 Lambdaの準備

東京リージョンにリソースを作成します(AWSCLIの設定であらかじめ東京リージョンにデフォルトで繋がるようにしています)

  1. Lambdaのロールを作成
    $ aws iam create-role --role-name navi-qiita --assume-role-policy-document '{"Version": "2012-10-17","Statement": [{ "Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
    {
        "Role": {
            "Path": "/",
            "RoleName": "navi-qiita",
            "RoleId": "AROA4MTWKLOMIZOLHCBGP",
            "Arn": "{ここに作成したロールのArnが記載される}",
            "CreateDate": "2024-03-29T17:43:18+00:00",
            "AssumeRolePolicyDocument": {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {
                            "Service": "lambda.amazonaws.com"
                        },
                        "Action": "sts:AssumeRole"
                    }
                ]
            }
        }
    }
    
    
  2. Lambda関数を作成する
    Arnにはロールを作成したときに返ってきたArnを入力する
    $ aws lambda create-function --function-name "NaviQiita" --runtime provided.al2023 --handler bootstrap --zip-file fileb://myFunction.zip --role arn:aws:iam::xxxxxxxx --architectures arm64
    
  3. 作成されたことを確認する
    AWSのLambdaの画面を開き、リソースが作成されていることを確認する
    image.png

3.アレクサスキルを作成しよう

Alexa公式ページの第1回: 初めてのスキル開発を参考にアレクサスキルを作成していきましょう
※記事が古いので一部UIが違う部分もあるので注意

参考 ↓

3.1 アレクサスキルの作成

  1. トップメニューよりAlexaを押下する
    image.png

  2. Alexaスキル開発を押下する
    image.png

  3. コンソールを押下する
    image.png

  4. Alexa開発者コンソールが開かれるので、スキルの作成を押下する
    作成したスキルはこの画面で後ほど確認することもできます
    image.png

  5. 各項目を入力し、次へを押下する
    スキル名:Alexaスキルの名前(好きなものを入力しよう)
    プライマリロケール:僕は日本語しかできないので日本語を選択
    image.png

  6. 各項目を選択し次へを押下する
    エクスペリエンスタイプ:ニュース(作るスキルに合わせて好きに選択してください)
    モデル:カスタム
    ホスティングサービス:独自のプロビジョニング
    image.png
    image.png

  7. スクラッチで作成を選択し、次へを押下する
    image.png

  8. 入力内容を確認し、スキルを作成するを押下する
    ボタン押下後、時間がたつと自動で画面が切り替わります。
    image.png

  9. 下記画面の通りになっていればOKです
    image.png

  10. スキルの呼び出し名を変更する
    今回はアレクサスキル名と同じにしていますが、呼び出し名の要件や、実際にアレクサにスキルを起動してもらうときに言いやすい、覚えやすい呼び出し名にすることをおすすめします。
    呼び出し名を変更後、画面右上のスキルをビルドを押下してください。
    image.png
    image.png

  11. Lambdaと紐づけ

Lambda側でトリガーの追加
作成したLambda関数の詳細画面に移動し、トリガー -> トリガーを追加を押下する
image.png
AlexaのAlexaSkillsKitを選択し、スキルIDには作成しアレクサスキルのIDを入力する。入力後追加を押下する
SkillIDはAlexaスキルのエンドポイントの画面より確認できる(後述)
image.png
トリガーが追加されたことを確認する。
次の手順で関数のARNが必要になるのでコピーしておく
image.png

エンドポイントを押下し、デフォルトの地域の欄に先ほど作成したLambdaのARNを入力します。
この画面で、スキルIDを取得できます
image.png
image.png
保存ボタンを押下し、画面右下に緑のメッセージが表示されればOK
image.png

3.2 スキルのテスト

  1. 開発者コンソール画面上部のテストを押下する

  2. スキルテストが有効になっているステージを開発中に変更する
    image.png

  3. テスト実行
    ナビキータ(スキル呼び出し名)を起動してと入力する
    Qiitaの記事のタイトルとURLが返ってきたら成功😎
    image.png

4.感想

アレクサスキルをLambda,golangを混ぜて作成してみて楽しかった。
Qiitaの記事タイトルとURLを返すようにしているがここらへんをもう少し工夫してアレクサスキルで実用的になるようにできればいいなと思った。
記事の中身をよみあげるなどなど。

ハマッタポイント

Lambdaにファイルをアップしたらパーミッションエラーで怒られた

Windows環境で、ファイルに適切なパーミッションをつけて圧縮しても効果がないらしい。(詳しい人おしえてください)
なので、公式が案内している方法でzipファイルを作成する必要があった

#### エラー内容
Error: fork/exec /var/task/bootstrap: permission denied

解決策

Windows での .zip ファイルの作成の手順通り圧縮すればいけた
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/golang-package.html#golang-package-windows

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?