DialogflowとLINE BotでConnpassの受付処理をスムーズにしてみた

クラスメソッドのせーのさんがAlexaを使ってConnpassの受付スキルを作成されていました。
https://dev.classmethod.jp/voice-assistant/try-to-develop-registration-skill/

それを実際に使ってみた所色々課題点が見えたので、
ほぼそのまま参考にして、処理を投げる部分は独自に今度はLINE Botを使って受付処理を作ってみました。

# Alexa受付を使ってみた。
実際にこの仕組を使って先日開催した東京がおまる塾で使ってみました。
スタッフが少しサポートするだけでとても画期的に使えました。

受付がとても近未来的な感じになってとても良かったと思います。
ただ、来場者の滑舌が悪かったり、周辺の音がうるさくて音声が聞き取れなくなったので、そこが課題点と感じました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Connpassの番号をAlexaに言うだけで受付が完了する<br>せーのさんが作った素晴らしいシステム<a href="https://twitter.com/hashtag/%E6%9D%B1%E4%BA%AC%E3%81%8C%E3%81%8A%E3%81%BE%E3%82%8B%E5%A1%BE?src=hash&amp;ref_src=twsrc%5Etfw">#東京がおまる塾</a> <a href="https://t.co/1mZ9A77Xhh">pic.twitter.com/1mZ9A77Xhh</a></p>&mdash; がおまる@スマートスピーカーアプリ開発入門発売中！ (@gaomar) <a href="https://twitter.com/gaomar/status/1130492113601171457?ref_src=twsrc%5Etfw">May 20, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 完成動画
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">LINEのチャットボットでConnpassの受付をスムーズにできるようにしてみました。<br>受付番号スキャンして読み取った番号をLINEに送信するだけで受付が完了します。<a href="https://twitter.com/hashtag/linedc?src=hash&amp;ref_src=twsrc%5Etfw">#linedc</a> <a href="https://t.co/RoShmD3BU1">pic.twitter.com/RoShmD3BU1</a></p>&mdash; がおまる@スマートスピーカーアプリ開発入門発売中！ (@gaomar) <a href="https://twitter.com/gaomar/status/1137204153657188352?ref_src=twsrc%5Etfw">June 8, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 動作確認
こちらからLINEで友だちになって、受付番号を`12345`か`54321`で試すことができます。

http://nav.cx/g1QJpdv
<a href="http://nav.cx/g1QJpdv"><img src="https://scdn.line-apps.com/n/line_add_friends/btn/ja.png" alt="友だち追加" height="36" border="0"></a>


# 1. Dialogflowの設定

## 1-1. MainIntentの設定
特に難しいことはしていません。必須入力にビジターカードNoを聞いていますが、LINE本社のセキュリティカード番号を記録する際の事務的な番号なので、通常は必要ありません。

| 項目      |       値 |
|:-----------------|:------------------|
|Intent名|MainIntent|
|Training phrases | ticketnumber (@sys.number)|

![s100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/1a1e383c-e55a-143b-4ad8-f562c5114b7a.png)

## 1-2. EndIntentの設定
これはConnpassの受付処理が終わったあとにレスポンスを返すためのインテントです。
Webhook先から設定したイベント名が飛んでくるので、インテントに設定します。

| 項目      |       値 |
|:-----------------|:------------------|
|Events|FINISH|
|PARAMETER NAME|myMessage|
|ENTITY|@sys.any|
|VALUE|#FINISH.message|
|Text Response|$myMessage|

![s101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/82063f09-9adc-1d22-6f43-7f29924eec52.png)

# 2. スプレッドシートの設定
Googleドライブでスプレッドシートを新規作成します。
ツールのスクリプトエディタからプログラムを記述します。

<img width="792" alt="s200.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/3c08fd80-864f-739d-2a44-a102f996036c.png">

## 2-1. GASプログラム
スプレッドシートを処理するプログラムを記述します。

```javascript
function findParticipant(sheet, ticketNumber, cardNumber) {
  var values = sheet.getDataRange().getValues();
 
  for (var i = values.length - 1; i > 0; i--) {
    var val = values[i][1];
    if (val == ticketNumber) {
      var rng = sheet.getRange(i + 1, 1);
      rng.activate();
      rng.setValue(true); // チェックボックスをつける
      rng = sheet.getRange(i + 1, 1, 1, 8);
      rng.setBackground("palegreen");
      
      // 受付日時を書き込む
      var tm = sheet.getRange(i + 1, 4);
      tm.activate();
      tm.setValue(new Date());

      // ビジターカードNoを書き込む
      var cardRng = sheet.getRange(i + 1, 5);
      cardRng.activate();
      cardRng.setValue(cardNumber);

      // 名前を取得して、Connpassの勉強会名を取得
      return values[i][2] + "さんの受付が完了しました。ようこそ" + values[0][3] + "へ！";
    }
  }
 
  return "missing";
}

function doGet(e) {
   var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('出欠シート');
   var res = ContentService.createTextOutput();
   var ticketNumber = e.parameter.ticketnumber;
   var cardNumber = e.parameter.cardnumber;  
   var retval = findParticipant(sheet, ticketNumber, cardNumber);  
 
   res.setContent(retval);
   return res;
 
}

```
## 2-2. URLを取得
ウェブアプリケーションとして導入をクリックして、URLを発行します。

<img width="574" alt="s201.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/e9f9c46a-6145-f9b1-086c-2ad8967da48a.png">

発行されるURLをメモします。
<img width="425" alt="s202.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/203cd46f-3713-a5e0-ceaa-764b8da61da7.png">

# 3. AWS Lambdaの設定
Dialogflowで設定しているWebhook先URLです。API Gatewayを経由してLambdaを実行しています。

## 3-1. API Gateway設定
特にこれも難しいことはしていません。API GatewayのサクセスURLを発行してください。

![s102.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/53448617-27c1-fb50-39ae-7d4ab9ad4330.png)

## 3-2. Lambdaプログラム
5〜6行目でDialogflowから飛んでくる値を取得しています。
11行目でスプレッドシートで処理した結果を取得して、22行目でDialogflowに返すイベントの設定をしています。

![s103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/d8318c46-fe55-fdfb-258e-2ad7356592e4.png)

```javascript:index.js
const request = require('request-promise');

exports.handler = async (event) => {
  const body = JSON.parse(event.body);
  const ticketnumber = body.queryResult.parameters.ticketnumber;
  const cardnumber = body.queryResult.parameters.cardnumber;
  var speechText = '';
  
  await regist(ticketnumber, cardnumber)
      .then(val => {
          speechText = val;
  });
  
  if (speechText === "missing") {
      speechText = `${ticketnumber}番の受付番号が見つかりません。もう一度Connpassの番号を入力してください。`;
  }

  return new Promise(function(resolve) {
      const responseJson = JSON.stringify({
        "fulfillmentText": "",
        "followupEventInput": {
          "name": "FINISH",
          "languageCode": "ja-JP",
          "parameters": {
            "message": speechText
          }
        }
      });
      var response = {
        statusCode: 200,
        headers: { "Content-type": "application/json; charset=UTF-8" },
        body: responseJson
      };
      resolve(response);
    });
};

const regist = (ticketnumber, cardnumber) => {
    let url = process.env.SPREADSHEET_URL + "?ticketnumber=" + ticketnumber + "&cardnumber=" + cardnumber;
    console.log(url);
    return request(url);
};
```

## 3-3. 環境変数の設定
環境変数は2-2で発行されたGASのURLを設定しています。

![s104.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/4cfe12f4-e1d6-0c50-1de9-4855c7c0ff39.png)

# 4. LINEの設定
MessagingAPIで設定します。特に説明はしません。アクセストークンの発行をします。

## 4-1. リッチメニューの設定
LINE Official Account　Manager画面へ遷移します。
https://manager.line.biz/

<img width="974" alt="s300.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/8ad15804-a074-6fa1-2545-0818cab3b69e.png">

リッチメニューから作成ボタンをクリックします。
<img width="1310" alt="s301.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/44f3945b-e2c1-62d5-047f-60b721a0156a.png">

表示期間を設定して、コンテンツの設定にあるアクションは`リンク`を選択します。
リンクのURLは`line://nv/camera`と入力します。たったこれだけで、画像をクリックするとカメラが起動します。

![s302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154355/e5a0faf2-5f34-e0df-a972-26e280c38ab1.png)

`line://nv/camera`で起動されるカメラアプリは既にOCRで読み取り機能が備わっています。
結果を自動的にLINE Botに返せるのでとても便利です。

# まとめ
GASのプログラムの部分はせーのさんのをほぼ流用させていただきました。
LINEのカメラ部分は何もせずにOCRの読み取り機能が使えるのでとても便利でした。
これを使って少しでもConnpassの受付が楽にできると嬉しいです。

システム化のご検討やご相談は弊社までお問い合わせください。
https://i-enter.co.jp/contact/