【ビール女子麦子さん④】Watson AssistantとLINE Messaging APIでランダムにスタンプを返す機能を作ってみた

#１．はじめに
「ビール女子🍺麦子さん」シリーズ、４回目の投稿です。

いままで麦子さんは、テキストでしか回答できなかったのですが、今回は**「スタンプを送ると、スタンプを返す機能」**を実装しようと思います。といっても、１種類のスタンプを固定で返しても面白くないので、**複数のスタンプの中からランダムに返す仕組み**にしようと思います。

ちなみに、ビール女子麦子さんとは、以下のようなWatson AssistantとLINE Messaging APIでつくった、ビールに詳しいチャットボットです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">つくってみたー！！中身はWatson Assistant(Watson Conversation)です。会話のスキル作るの楽しい！！<br>これからビールの知識を増やして立派なビール女子に育てます😃 <a href="https://t.co/nZfuqH4IfC">pic.twitter.com/nZfuqH4IfC</a></p>&mdash; はぁこ🌸ビール女子麦子開発中 (@paco_itengineer) <a href="https://twitter.com/paco_itengineer/status/1119612368240005120?ref_src=twsrc%5Etfw">April 20, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 


#２．仕組みの検討
使うのはいつも通りこの３つです。
・WatsonAssistant
・Node-RED
・LineMessagingAPI

###（１）スタンプが送られてきたことの認識
[Messaging APIリファレンス](https://developers.line.biz/ja/reference/messaging-api)の「Webhookイベントオブジェクト」ー「messageプロパティ」ー「スタンプ」を見ると、スタンプが送られてきた場合は、**messageオブジェクトの"type"が"sticker"になる**とされています。

実際に、Node-REDのデバッグログで、スタンプを送ったときのWebhookイベントオブジェクトを見てみると、確かに**"type"が"sticker"**になっています。

これでスタンプが送られてきたことが認識できそうです。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/f515a666-4809-2af5-b88d-8df4952faae4.png)

###（２）スタンプの返し方
次にスタンプの返し方を確認しましょう。[Messaging APIリファレンス](https://developers.line.biz/ja/reference/messaging-api)の
「メッセージオブジェクト」の「スタンプメッセージ」を見ると、以下のように**"type","packageId","stickerId"をStringで設定する**とされています。

```
{
  "type": "sticker",
  "packageId": "1",
  "stickerId": "1"
}
```

ちなみに、"packageId"と"stickerId"は[スタンプリスト](https://developers.line.biz/media/messaging-api/sticker_list.pdf)から確認ができます。

これでスタンプの返し方もわかりました。

###（３）「ランダムに」スタンプを返す方法
固定のスタンプを返すだけであれば、Webhookのmessageプロパティのtypeが"sticker"の時に、固定のメッセージオブジェクトを返せばいいのですが、それでは面白くありません。そこで、**複数のスタンプの中からランダムで返す仕組み**を考えてみました。

【ランダムにスタンプを返す仕組み】
①Webhookのmessageプロパティのtypeが"sticker"であることを認識
②WatsonAssistantに渡すメッセージに「スタンプを送って」という文字列を設定
③WatsonAssistantは「スタンプを送って」というIntentを受け取ったら、テキストのランダム回答機能で複数のstickerIdの中から１つのstickerIdを返却
④WatsonAssistantの返却した結果が「0~99999999」の場合はstickerIdと認識
（WatsonAssistant側に数字のみを回答する機能は他にないためこの実装が可能）
⑤stickerIdが返ってきた場合は、メッセージオブジェクトにスタンプメッセージとして"type","packageId","stickerId"を設定

![99.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/3d675b8f-64e7-f054-a6f4-aeaece2c5e98.png)




これで、**「スタンプを送ると、スタンプを返す機能」**ができるのではないかと考えました。

#３．実装
それでは実装していきましょう。実際の麦子さんは度重なる機能追加でかなり複雑化していますので、シンプルに説明するために[【ビール女子麦子さん】 IBM WatsonとLINEでbotを作ってみた](https://qiita.com/paco_itengineer/items/5981c22edc60494383e6)の時点のNode-REDへ追加するイメージで書きます。初期状態を以下の状態とします。

![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/9573552a-a6c1-28d7-59a6-6c8503974261.png)


###①Webhookのmessageプロパティのtypeが"sticker"であることを認識
・「Switch」のノードを以下のように設定し、"sticker"とそれ以外で別のフローに流れるようにします。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/70096e2c-3852-aa36-8b02-2e5bb965e7eb.png)

###②WatsonAssistantに渡すメッセージに「スタンプを送って」という文字列を設定
・「Change」のノードを以下のように、WatsonAssistantに送信するメッセージに「スタンプを送って」という文字列を設定します。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/546e7053-01d0-5bb7-b710-56fc5369ebc5.png)



・これらを以下のように並べで、Typeがstickerの時に「スタンプを送って」という文字列をWatsonAssistantに送るようにします。
![４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/9651858d-601d-680a-6adb-1400d0f878e7.png)

###③WatsonAssistantは「スタンプを送って」というIntentを受け取ったら、テキストのランダム回答機能で複数のstickerIdの中から１つのstickerIdを返却
WatsonAssistant側に移って、機能を実装していきましょう。

【手順】
・WatsonAssistantの「Intents」に「スタンプを送って」を登録。
・Dialogsに「スタンプ」というノードを作成し、「#スタンプを送って」のIntentsの時に、stickerIdをランダムに返すように設定。

※"packageId"と"stickerId"は[スタンプリスト](https://developers.line.biz/media/messaging-api/sticker_list.pdf)から確認
![４.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/ba3cf63a-5bed-7511-225c-fe9a6c6c0c37.png)

###④WatsonAssistantの返却した結果が「0~99999999」の場合はstickerIdと認識
ここからは、Node-REDに戻ります。

・「Switch」のノードを以下のように設定し、WatsonAssistantの返却した結果が「0~99999999」の時と、それ以外で分岐させます。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/c0fcd927-535f-dd0d-164c-0e4eb6492c59.png)


###⑤stickerIdが返ってきた場合は、メッセージオブジェクトにスタンプメッセージとして"type","packageId","stickerId"を設定
・「Change」のノードを以下のように設定し、スタンプメッセージを送るようにします。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/f919bbda-9b07-a567-f2c5-cbd079e55e9c.png)

「対象の値」の中身は以下のようにしました。

```
[
   {
       "type":'sticker',
       "packageId":'11537',
       "stickerId":msg.payload.output.text[0]
   }
]
```

・これらを以下のように配置します。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299024/80200342-9dbd-d7a5-4431-5330a4a9d30a.png)


これでデプロイしたら完成です！！！！

#４．できあがり！
こんな感じになりました！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">普通にスタンプを送れば、麦子さんがスタンプを返してくれるようにもなってます！ <a href="https://t.co/zQQdFLyVos">pic.twitter.com/zQQdFLyVos</a></p>&mdash; はぁこ🌸ビール女子麦子開発中 (@paco_itengineer) <a href="https://twitter.com/paco_itengineer/status/1126106590837334016?ref_src=twsrc%5Etfw">May 8, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

よかったら使ってみてくださいね！

ビール女子🍺麦子さん　
　　↓↓↓↓↓
<a href="http://nav.cx/aLo5a15"><img src="https://scdn.line-apps.com/n/line_add_friends/btn/ja.png" alt="友だち追加" height="36" border="0"></a>