Alexaスキルに通知機能を実装してみた

#概要
Alexaスキルでは、スキルを利用しているユーザーに、プロアクティブAPIを利用して通知を送ることができます。
今回は、コードよりもスキルのマニフェストを少し細かく載せておきます。

#プロアクティブイベントAPI
[プロアクティブイベントAPI（公式）](https://developer.amazon.com/ja-JP/docs/alexa/smapi/proactive-events-api.html)
プロアクティブイベントAPIを使用すると、スキルの ClientId と ClientSecret を利用してトークンを発行することでスキルを使用している全ユーザーまたは、userId を利用して特定のユーザーに通知を送ることができます。
通知には定型文があり、[イベントカタログ](https://developer.amazon.com/ja-JP/docs/alexa/smapi/schemas-for-proactive-events.html#event-catalog)の中から選択する必要があります。（定型文の追加をリクエストすることも出来るようです）

#実装してみた
##事前に準備するもの
- Alexaスキル
  - Alexa Developer Console で適当なスキルを作成しておきます。
- AlexaスキルのEndpoint (Lambda)
- Alexaスキルの通知設定の変更を受け取るEndpoint (Lambda：alexa-skill-proactive-events)

##1. スキルのマニフェストを変更する
###追記 2021/06/13
以下ではSMAPIを使用して通知のパーミッションを追加していますが、Alexa Developer Console で変更できるようになっていました！現段階で確認できているのはマルチ機能スキル(MCS)のみですが、今後カスタムスキル、スマートホームスキルでも Alexa Developer Console から変更できるかもしれません。
###SMAPIによる変更
スキルで通知機能を実装するためにマニフェストを変更する必要があります。
Alexa Developer Console では変更できないため、[SMAPIを使用してプロアクティブイベントを定義](https://developer.amazon.com/ja-JP/docs/alexa/smapi/proactive-events-api.html#onboard-smapi)します。
まず、[スキル情報の取得API](https://developer.amazon.com/ja-JP/docs/alexa/smapi/skill-operations.html#get-skill-information)で事前に作成しておいたスキルのマニフェストを取得します。
次に、取得したスキルのマニフェスト（skill.json）に以下のように events, permission を追加します。

```skill.json
    "events": {
      "publications": [
        {
          "eventName": "AMAZON.MessageAlert.Activated"
        }
      ],
      "subscriptions": [
        {
          "eventName": "SKILL_PROACTIVE_SUBSCRIPTION_CHANGED"
        },
        {
          "eventName": "SKILL_PERMISSION_ACCEPTED"
        }
      ],
      "endpoint": {
        "uri": "arn:aws:lambda:us-east-1:xxx:function:alexa-skill-proactive-events"
      }
    },
    "permissions": [
      {
        "name": "alexa::devices:all:notifications:write"
      }
    ]
```
- `events.publications`では、[イベントカタログ](https://developer.amazon.com/ja-JP/docs/alexa/smapi/schemas-for-proactive-events.html#event-catalog)の中から通知する形式を設定します。
今回は、「山田太郎からのメッセージが5件あります」という形式の通知を送るため、`AMAZON.MessageAlert.Activated`を設定しています。
- `events.subscriptions`では、Endpoint にイベントが送られてくるタイミングを設定します。
スキルの通知設定を有効にしたとき（`SKILL_PROACTIVE_SUBSCRIPTION_CHANGED`）とスキルの権限を変更したとき（`SKILL_PERMISSION_ACCEPTED`）にイベントが送られてくるように設定しています。通知を特定のユーザーに送るときに必要な userId を accessToken と紐づけるために設定しています。どちらもユーザー全員に通知を送るだけだと不要です。
- `events.endpoint`では、事前に準備した Endpoint を設定します。
`events.subscriptions`で設定したタイミングでイベントが送られてくるため、必要な情報を DynamoDB 等に保存しておきます。
- `permissions`では、スキルの権限を設定します。
通知を送るために`alexa::devices:all:notifications:write`を設定しています。

マニフェストを変更したら、[既存スキルの更新API](https://developer.amazon.com/ja-JP/docs/alexa/smapi/skill-operations.html#update-a-skill)でスキルのマニフェストを更新します。
##2. 通知をおくる
まず、通知をおくるためにはスキルの clientId, clientSecret が必要になるため、Alexa Developer Console で確認します。**ビルド**タブの**アクセス権限**から確認できます。
次に、[アクセストークン取得API](https://developer.amazon.com/ja-JP/docs/alexa/smapi/proactive-events-api.html#request-format)を使用してアクセストークンを取得します。
最後に、[プロアクティブイベントAPIを呼び出す](https://developer.amazon.com/ja-JP/docs/alexa/smapi/proactive-events-api.html#call-proactive)ことで通知を送ることができます。
コードについては省略します。
通知を送ると Amazon echo が点滅するので「通知教えて」と喋りかけると通知の内容を教えてくれます。

#参考リンク
- [プロアクティブイベントAPI（公式）](https://developer.amazon.com/ja-JP/docs/alexa/smapi/proactive-events-api.html)
- [スキルの管理（公式）](https://developer.amazon.com/ja-JP/docs/alexa/smapi/skill-operations.html)
- [alexaで通知を飛ばしてみる](https://developer.amazon.com/ja-JP/docs/alexa/smapi/proactive-events-api.html#call-proactive)