ClovaスキルからLINE BOTでメッセージを送信するまで（CEK SDK Node.js）


# はじめに
LINE Clovaスキルの開発キット(CEK: Clova Extensions Kit)が公開され、各言語のSDKも公開されました。

Clovaの魅力は、やはりスマホのLINEアプリ連携でしょ！
ということで、ClovaのSDK(Node.js版)で作ったスキルから、LINE BOTを使ってスマホのLINEアプリにメッセージを通知するまでをやってみます。

例として、Clovaに「牛乳なくなった」と話すと、LINEアプリに「牛乳買う」というメモを送るスキルを作ってみます。

*) BOTはプッシュ通知を送るのみで、ユーザーからの返信はやりません。
*) トライアル環境で試してみるだけで、実運用はできません。
*) Clova CEK, LINE BOTはじめてなので、間違いなどあればご指摘ください。

## 環境
- CEK SDK : Node.js版, v1.1.0
- BOT SDK : 公式Node.js版, v6.1.0
- Messaging API : Developer Trial
- ngrokでローカル(mac)にデプロイ

# 準備
LINE Developersに登録し、プロバイダを作成済みの状態にします。

手順はこちら
[Messaging APIを利用するには](https://developers.line.me/ja/docs/messaging-api/getting-started/)

# LINE BOTの作成
先にBOTの方を用意しておきます。
今回は通知を一方的にプッシュ通知するだけのものとします。
メッセージの内容はClovaスキル側で入れるので、中身は空っぽです。

###1. Messaging APIでチャネルを作成
LINE Developersのプロバイダのトップで、"新規チャネル作成"を選択し、"Messaging APIでチャネルを作成する"を選びます。
<img width="600" alt="スクリーンショット 2018-08-26 21.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/3b5b2b92-64b5-9567-9d56-af766425b230.png">

###2. 基本情報の入力  
フォームに沿って各情報を入力します。すべて必須入力です。

- アプリ名 : LINEに表示されるBOTの名前です。
- アプリ説明 : BOTの説明。
- プラン : プッシュ通知を試したいので、"Developer Trial"で。
- 大業種、小業種 : よしなに。
- メールアドレス : よしなに。

確認、利用規約に同意して作成完了です。

###3. BOTの設定
BOTの各種設定をします・・・と言っても、ほぼやることないです。
アクセストークンの発行だけしておきます。
<img width="600" alt="スクリーンショット 2018-09-02 6.24.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/96909ef6-2219-41f4-6596-265c35c07100.png">


画面の末尾に友だち追加用のQRコードが表示されてますので、スマホのLINEアプリで友だち登録しましょう。

Clova側のドキュメントには、LINE@の場合にWebhookや自動応答の設定をするよう書かれていますが、今回は設定なしにしておきます。
（参考）[Custom ExtensionとLINEを連携する](https://clova-developers.line.me/guide/#/CEK/Guides/Link_Messaging_API.md)

###4. ちゃんと届くかチェック
curlでAPIを直接呼んで、通知が届くか試せます。

```
curl -X POST \
-H 'Content-Type:application/json' \
-H 'Authorization: Bearer {ここにアクセストークンを記述}' \
-d '{
    "to": "ここにユーザーIDを記述",
    "messages":[
        {
        "type": "text",
        "text": "{メッセージ}"
    }
    ]
}' https://api.line.me/v2/bot/message/push
```

（参考）https://news.mynavi.jp/article/linebot-2/

# Clovaスキルの作成
つづいて、Clovaのスキルです。
発話内容に応じて、音声で応答を返したり、LINE BOTにメッセージを送ったりします。

### 1. Clovaスキルのチャネルを作成
LINE Developersのプロバイダで、今度は"Clovaスキル"でチャネルを作成します。
<font color="Crimson">必ずBOTと同じプロバイダ配下で作成してください。</font>
<img width="600" alt="スクリーンショット 2018-08-26 21.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/fe3cf273-7ce6-1619-409b-5a47d5d9f728.png">

チャネル名を入力して作成完了させます。
以降の作業はClova Developer Centerで行います。

### 2. スキル基本情報の入力
LINE Developersのプロバイダーで、今度は"Clovaスキル"でチャネルを作成します。
<img width="600" alt="スクリーンショット 2018-08-26 21.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/d44aee87-041b-2769-ec73-8002086fe238.png">

- スキル名 : スキルの表示名です。適当に"リマインダー"としておきます。
- 呼び出し名（メイン） : 音声で呼び出す際の呼び名です。"リマインダー"としておきます。
- 呼び出し名（サブ） : 全く別の呼び方でも起動できます。特に指定しません。
- AudioPlayerの使用 : いいえ
- 提供者区分 : よしなに。
- Extensionと連携するLINEのアカウント : 先程作成したLINE BOTを選択します。

ここまでを保存し、設定をすっ飛ばして"個人情報の保護および規約同意"を選択します。
<img width="600" alt="スクリーンショット 2018-08-26 21.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/342f4638-fe6a-068a-6124-5e12c887caba.png">

で、"対話モデル"を選んで、発話の処理を設定する画面に移ります。
<img width="400" alt="スクリーンショット 2018-08-26 21.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/f76191dc-6237-1bf8-a7a6-b2977a4d1311.png">

### 3. 対話モデルの作成
ユーザーが「牛乳なくなった」と発話した際に呼び出される動作と、そこから「牛乳」というキーワードを抽出する処理を設定します。
「牛乳なくなった」という命令全体は"インテント"、「牛乳」のような変数部分は"スロット"と呼びます。

#### 3.1. スロットの作成
スロットには、開発者が項目を自由に追加できるカスタムスロットタイプと、数字や都市の名前など予め定義されているビルトインスロットタイプがあります。
今回はダッシュボードから、カスタムスロットタイプの+ボタンを押して新たなスロットタイプを作成します。
<img width="600" alt="スクリーンショット 2018-08-26 21.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/b4c44d2a-36a4-a450-4505-7a9c30692d06.png">
スロットのタイトルを入力して作成します。今回は"Target"としておきました。
<img width="600" alt="スクリーンショット 2018-08-26 21.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/9db678ed-0068-e89d-1196-2a9efc0915df.png">

つづけて、どのような単語をスロット値として認識するか設定します。
```スロットの新たな代表語を入力``` に"牛乳"や"卵"といった品名を入力します。
同義語欄を入力すると、別の言い方や言い間違いを同じ値として識別できるようになります。
例のように登録すると、"ミルク"も"牛乳"として扱われます。
![スクリーンショット 2018-08-29 6.35.15.png](https://qiita-image-store.s3.amazonaws.com/0/64046/fe6af487-5a5c-6100-2904-2a02f42bfb85.png)
入力したら"保存"ボタンを押します。

#### 3.2. インテントの作成
ダッシュボードに戻り、今度はカスタムインテントの+ボタンを押します。
インテント名は"ReminderIntent"としておきました。
![スクリーンショット 2018-08-29 6.41.08.png](https://qiita-image-store.s3.amazonaws.com/0/64046/0b148a9b-afc7-f190-565f-206dfbea0a76.png)

まず、インテント内で使う変数=スロットを登録しておきます。
インテント中で使う名前(例ではtarget)を入力し、型として先程登録した"Target"を設定します。
![スクリーンショット 2018-08-29 6.45.04.png](https://qiita-image-store.s3.amazonaws.com/0/64046/7840f460-3359-9eb6-ea73-1b3e3dc56bd3.png)

つづいて、ユーザーがどう話しかけたら反応するかのサンプル発話の定義です。

サンプル発話リストに、想定する発話の全文「牛乳なくなった」と入力します。
そして、"牛乳"の部分をスロットにするため、"牛乳"の文字をドラッグします。
![スクリーンショット 2018-08-30 0.08.42.png](https://qiita-image-store.s3.amazonaws.com/0/64046/1881b287-c045-3e8e-2db5-20ad7b4ed618.png)
すると、スロットの候補が表示されますので、targetを選択します。
同様の手順で、「牛乳欲しい」「牛乳買ってこいや」など思いつく文章を入力してききましょう。

気が済んだら保存を押して完了です。

#### 3.3. ビルド
ビルドボタンを押して、ここまで入力した対話モデルをビルドします。
数分かかりますので、次のNode.jsプログラムの準備にとりかかります。

### 4. Node.jsプログラムの作成
対話モデルはユーザーの発話を認識し、インテントとスロットに分解するまでを行います。
それに応じてどう返事をするか、なにかサービスを動かすかなどはサーバー上のプログラムに実装します。
CEKから届くリクエストのJSONをそのまま処理しても良いですが、公式に各言語のSDKが用意されているので、それを使うことにします。

今回はNode.js版のSDKで実装してみます。
https://github.com/line/clova-cek-sdk-nodejs

#### 4.1 Node.js版 SDKのインストール
開発用のフォルダを作って、npmでClova CEK SDKとLINE BOTのSDKをインストールします。

```
$ npm init --yes
$ npm install --save @line/clova-cek-sdk-nodejs @line/bot-sdk express
```

#### 4.2 プログラム作成
index.jsファイルを作成し、以下のようなソースコードを書きます。

```index.js
const clova = require('@line/clova-cek-sdk-nodejs');
const express = require('express');
const line = require('@line/bot-sdk');

const client = new line.Client({
  channelAccessToken: "YOUR_ACCESS_TOKEN" //Messaging APIのアクセストークン
});

const clovaSkillHandler = clova.Client
  .configureSkill()
  .onLaunchRequest(responseHelper => {
    responseHelper.setSimpleSpeech({
      lang: 'ja',
      type: 'PlainText',
      value: 'リマインダーです。何を買いますか？',
    });
  })
  .onIntentRequest(async responseHelper => {
    const intent = responseHelper.getIntentName();
    const userId = responseHelper.getUser().userId;
    
    switch (intent) {
      case 'ReminderIntent':
        const target = responseHelper.getSlot("target");
        
        //LINEプッシュ通知
        client.pushMessage(userId, {
          type: 'text',
          text: target + '買う'
        });

        //音声のレスポンス
        responseHelper.setSimpleSpeech({
          lang: 'ja',
          type: 'PlainText',
          value: target + '、ですね。' + 'わかりました',
        });

        responseHelper.endSession();
        break;
    }
  })
  .onSessionEndedRequest(responseHelper => {
    // Do something on session end
  })
  .handle();

const app = new express();
const clovaMiddleware = clova.Middleware({ applicationId: "YOUR_APPLICATION_ID" }); //Extension ID
// Use `clovaMiddleware` if you want to verify signature and applicationId.
// Please note `applicationId` is required when using this middleware.
app.post('/clova', clovaMiddleware, clovaSkillHandler);

// Or you can simply use `bodyParser.json()` to accept any request without verifying, e.g.,
//app.post('/clova', bodyParser.json(), clovaSkillHandler);

const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Server running on ${port}`));
```
GitHub) https://github.com/Omoti/clova-linebot-sample-nodejs

#### 4.3 解説
CEK SDKのREADMEにあるサンプルをベースにしています。
https://github.com/line/clova-cek-sdk-nodejs

それぞれ、環境に応じて書き換えてください。
- YOUR_ACCESS_TOKEN : Messaging APIのアクセストークン
- YOUR_APPLICATION_ID : ClovaスキルのExtension ID


```onLaunchRequest``` でスキル起動時の処理、```onIntentRequest```の中のswitchでカスタムインテントの処理を用意します。

```getSlot``` でtargetスロットを取得しており、「牛乳なくなった」の「牛乳」が得られます。

```js

const target = responseHelper.getSlot("target");
```


```setSimpleSpeech``` がClovaが音声でしゃべる内容ですね。

```client.pushMessage``` で指定したユーザーIDにメッセージを送信します。
ここで、以下のようにユーザーIDを取得すると、Clovaスキルを使っているLINEユーザーに対してメッセージを送信することができます。

```js

//ClovaスキルのセッションのユーザーIDを取得
const userId = responseHelper.getUser().userId;
```

###5. スキルとNode.jsプログラムの結合
#### 5.1. 起動してngrokで公開
Node.jsプログラムを起動します。

```
node index.js
```

ngrokで、外部からアクセスできるようにします。

```
ngrok http 3000
```

#### 5.2. スキルと接続
Clova Developer Centerに戻り、スキルのサーバー設定、"ExtensionサーバーのURL"にngrokのURLを登録します。サンプル通りに実装した場合、<font color="Crimson">URL末尾に"/clova"をつける</font>のを忘れないようにしましょう。
<img width="1265" alt="スクリーンショット 2018-08-31 6.44.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/bc9f798b-972d-34a8-410e-41ee1eb4b4f4.png">

これで、LINE BOTにメッセージを送るClovaのスキルができました。

# 動かしてみる
Clovaの実機と、スマホのLINEアプリで実際に動作させてみましょう。
「クローバ、リマインダーを開いて」
「牛乳なくなった」
と話しかけます。
<img width="336" alt="スクリーンショット 2018-08-31 23.06.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/f12fa326-345a-a0b6-5cd1-a36c0ea16703.jpeg">

ちゃんとLINEに「牛乳買う」とメッセージが届きました！
<img width="336" alt="スクリーンショット 2018-08-31 23.06.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/64046/f66314d0-9a7f-8727-6b20-d6b7f3e89a7a.png">

# おわりに
SDKを使って、簡単にClovaスキルからLINE BOTでメッセージを送ることができました。
やはり、普段よく使うLINEと連携しやすいのは良いですね。そこからの展開にも期待できます。

実際に運用するには、BOTからの通知に費用がかかったり、"ユーザーが該当のボットからメッセージが来ると理解できること"などの利用条件が定められているので注意が必要です。

利用条件）
[Custom ExtensionとLINEを連携する](https://clova-developers.line.me/guide/#/CEK/Guides/Link_Messaging_API.md)

## 参考
Clova公式SDK(Node.js)の使い方まとめ
https://qiita.com/miso_develop/items/6b256c1e8757c0ace4a9

ClovaからLINEアプリに通知する(Messaging APIなるものを使ってみる)
https://qiita.com/imajoriri/items/3a62eb95236425a44a1b