Alexaスキルを無効化されたときに処理を実行する

Alexaスキルを無効化した際のイベントについて調べました。

理由としては、当時開発中のスキルでPersistentAttributesを使っていて、これ、ユーザーがスキル無効化したらそのイベントを拾って該当ユーザーのPersistentAttributes情報を削除したほうがきれいだよなあと考えたからです。

結論からいうと実現できました。
以下、その流れを書いていきますがASK-CLIをある程度使ったことがあるor理解している方でないと少し難しいかもしれません。

#スキル無効化時に送信されるリクエスト情報

こちらにスキル無効化時のイベントについて記載があります。

[Alexaスキルのスキルイベント#スキル無効化イベント](https://developer.amazon.com/ja/docs/smapi/skill-events-in-alexa-skills.html#skill-disabled-event)

以下のような感じでリクエストが送信されるようです。
どこに送信されるか、という情報は後述の設定ファイル(skill.json)に記載することになります。

``` json
{
  "version": "string",
  "context": {
    "System": {
      "application": {
        "applicationId": "string"
      },
      "user": {
        "userId": "string"
      },
      "apiEndpoint": "https://api.amazonalexa.com"
    }
  },
  "request": {
    "type": "AlexaSkillEvent.SkillDisabled",
    "requestId": "string",
    "timestamp": "string",
    "body": {
      "userInformationPersistenceStatus": "PERSISTED"
    }
  }
}
```

# スキル無効化イベントのハンドラを実装してみる

実際にスキル無効化時に処理を実行する仕組みを実装してみました。

以下の感じでできました。

1. skill.json にスキル無効化イベント情報を受け取るLambda関数情報の記載を追加
2. 1.に記載したLambda関数にスキル無効化イベントハンドラを実装
3. デプロイする

# 1. skill.json にイベント情報を受け取るLambda関数情報の記載を追加
skill.jsonはASK-CLIで引いてくる感じになります。
以下の記事のような感じでskill.jsonを引いてくれます。
ちなみに私は作成済のスキルをask cloneして一式をローカルに落としました。
[ask-cliで作成済みのAlexa skillの情報を取得する](https://wp-kyoto.net/import-alexa-skill-data-by-ask-cli)

こちらの記事にskill.jsonの記載追加について詳しく書かれています。
(スキル有効化イベントの方も一緒に書かれています)
[[Alexa] スキルイベントを使ってスキルが有効/無効化されたらSlackに通知してみる](https://dev.classmethod.jp/voice-assistant/amazon-alexa/alexa-skill-event-notfication-with-slack/)

記事にある通り、skill.jsonに以下のようにeventsの記載を追加します。

``` skill.json
  "manifest": {
    "apis": {
      "custom": {
        "endpoint": {
          "uri": "【スキルのバックエンドLambdaのARN】"
        },
        "interfaces": []
      }
    },
    "events": {
      "subscriptions": [
        {
          "eventName": "SKILL_DISABLED"
        }
      ],
      "endpoint": {
        "uri": "【無効化イベント送信先LambdaのARN】"
      }
    },
    "manifestVersion": "1.0",
    （以下省略）
}
```

# 2. 1.に記載したLambda関数にスキル無効化イベントハンドラを実装

今回、私はスキルのバックエンドLambdaと無効化イベント送信先Lambdaを同じ向き先にしてみましたが、その方法でもOKなようです。
request.typeで判定できますね。

Lambda側に以下のようにハンドラを実装すれば良いです。
PersistentAttributesを空にする処理を書いてみました。
(レスポンスどうすればよいかわからなかったけど、とりあえず返すだけ返している。。。)

``` Node.js
// スキル無効化イベントハンドラ
const SkillDisabledEventHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'AlexaSkillEvent.SkillDisabled';
    },
    async handle(handlerInput) {
        // スキル無効化のリクエストが送信された場合に実行する処理

        // 永続アトリビュートオブジェクトの中身を空にする
        handlerInput.attributesManager.setPersistentAttributes(null);

        return handlerInput.responseBuilder
            .getResponse();
    }
};
```

**(2019/11/04 追記)
スキル無効化時に無条件にPersistentAttributesを空にしてよいとは限らないので、ご注意ください。
たとえば、消費型のスキル内課金を実装している場合、PersistentAttributesを安易に削除してしまうと危険です。
(スキル無効化後に再度有効化しても、課金した状態が維持されている必要があるため)
細かい内容は公式のリファレンスを参照してください。**

**■Alexaスキルのスキルイベント - スキル無効化イベント
https://developer.amazon.com/ja/docs/smapi/skill-events-in-alexa-skills.html#skill-disabled-event**

**■スキルコードにISPのサポートを追加する - ユーザーがスキルを無効化してから再有効化した場合にユーザーインベントリーを管理する
https://developer.amazon.com/ja/docs/in-skill-purchase/add-isps-to-a-skill.html#maintain-inventory**

**(2019/11/04 追記ここまで)**

# 3. デプロイする
修正したskill.jsonとLambda側関数をデプロイします。
Lambda側はブラウザ上で直接コーディングでもzipで固めてアップロードでもいいと思いますが、
skill.jsonは取得した時と同様にASK-CLIでデプロイする必要があります。
前述のサイトなんかを参考にして、ask deployなりask uploadなりすれば良いです。

# まとめ
スキル無効化イベントを取得し、処理することができました。
スキル無効化時はリクエストに含まれる情報が少なめなので、できることがそんなに多くないかもしれません。
今回はスキル無効化について書いてますが、スキル有効化時など、ほかのいくつかのイベントについてもリクエスト送信されるみたいなので、有効活用できたら面白そうです。

# 参考URL
[Alexaスキルのスキルイベント](https://developer.amazon.com/ja/docs/smapi/skill-events-in-alexa-skills.html)
[ask-cliで作成済みのAlexa skillの情報を取得する](https://wp-kyoto.net/import-alexa-skill-data-by-ask-cli)
[[Alexa] スキルイベントを使ってスキルが有効/無効化されたらSlackに通知してみる](https://dev.classmethod.jp/voice-assistant/amazon-alexa/alexa-skill-event-notfication-with-slack/)