LINE Bot (LINE MESSAGING API)の個人的開発7Tips


はじめに


この記事は、9/23実施の
Arumon Lightning Talk 向けの記事です。

  • この記事で書くこと

    • LINE Bot をいくつか開発して思ったTips(ほぼ当たり前のこと)の紹介
    • (ケーススタディとして)実際に @kodomoEBINA が作った LINE Bot の紹介
  • この記事に書かないこと

    • LINE Bot のハンズオン的な開発手順の説明
    • push通知の実装など(いずれ他の記事で)
  • この記事読んでためになりそうな人

    • LINE Bot でどんなことができるかのイメージが湧いていない人
    • LINE Bot 開発してみたいけど、どうすればいいかのイメージが沸かない人
    • LINE Bot 開発駆け出しの人

開発に必要なもの

LINE Bot (LINE MESSAGING API) とは

基本的には、右から左へ受け流すムーディ勝山的な存在
できることは大きく以下の二つ

  • リプライ (←今回の説明対象)
    • メッセージ受け取って、そのまま自作のプログラムに受け流す
    • 自作のプログラムでの実行結果を受け取って、ユーザにメッセージとして送る

  → 複雑そうな処理は全部裏側を自作する必要がある

  • プッシュ通知
    • ユーザに一方的にメッセージを送りつける
    • ただし、無料/低価格プランの場合、回数制限あり

LINE Bot の基本構成

登場人物たちの解説

  • LINE Bot (LINE MESSAGING API)

  • Google Apps Script (GAS)

    • メッセージを受け取って処理するための自作プログラム
    • Google Cloud Functions (GCF) や Lambda などでも代用可
    • ちなみに、GASの場合、言語はJavascript(node.js)
  • Firebase Realtime Database / Firestore

    • ユーザ登録などで必要
    • 一つの処理に複数回往復が必要になる場合は必要(=ほぼ絶対必要)
    • 他のDBでももちろん代用可。今回はGASとの親和性の高さを重視

開発の流れ

  1. 何をやらせるか(=持たせたい機能)を考える
  2. 処理フローをざっくり考える
  3. 環境を準備する
  4. 細かいメッセージタイプとか考えつつ、開発→デプロイ→テスト のサイクルを回す

0.ケーススタディの前座 - 「投資王」を例に

1. 何をやらせるか(=持たせたい機能)を考える


細かくは割愛

  • 投資王における機能一覧
    • ユーザ登録
    • 金融商品の現在価格表示(リクエストベース)
    • 金融商品の売買
    • 売り時タイマー:特定の商品がとある価格より上回った時のお知らせ機能

2. 処理フローをざっくり考える


「投資王」の例のように、どんなやりとりにするかのシナリオをざっくりイメージする

用例

  • → <処理内容>   :ユーザからBotへ
  • ← <処理内容>   :Botからユーザへ
  • (-- <処理内容> --) :Bot内処理

例1:金融商品の現在価格表示

  • → 金融商品の現在価格表示リクエスト
  • (-- 価格情報が乗っているDBの情報を取得 --)
  • ← 価格一覧を返す

例2:ユーザ登録

  • → 登録リクエスト
  • ← 登録名を聞く
  • → 登録名を入力/回答
  • (-- DBに情報を登録&所持金として100万円を付与 --)
  • ← 登録完了の旨をリプライ

例3:金融商品の売買

  • → 売り/買い リクエスト
  • ← 売買対象を聞く
  • → 対象を回答
  • ← 数量を聞く
  • → 数量を回答
  • (-- 売買処理 --)
  • ← 処理結果を返す

3. 環境を準備する

Tips参照のため、割愛

4. 細かいメッセージタイプとか考えつつ、開発する

座学:受け渡されるメッセージの体型を理解する

とりあえず、以下のソースをGASにはっつけてそのままデプロイすると
何を言っても「こんにちは」で返してくれるBotが作れる。

LINE BOTの作り方(外部リンク) より引用

sample.js
function doPost(e) {
  var replyToken= JSON.parse(e.postData.contents).events[0].replyToken;
  if (typeof replyToken === 'undefined') {
    return;
  }

  var url = 'https://api.line.me/v2/bot/message/reply';
  var channelToken = 'ここにアクセストークン(ロングターム)を貼り付け';

  var messages = [{
    'type': 'text',
    'text': 'こんにちは',
  }];

  UrlFetchApp.fetch(url, {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + channelToken,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': messages,
    }),
  });
  return ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON);
}

まず、doPost(e)eの中身を理解する。

{
  "destination": "xxxxxxxxxx",
  "events": [
    {
      "replyToken": "0f3779fba3b349968c5d07db31eab56f",
      "type": "message",
      "mode": "active",
      "timestamp": 1462629479859,
      "source": {
        "type": "user",
        "userId": "U4af4980629..."
      },
      "message": {
        "id": "325708",
        "type": "text",
        "text": "Hello, world"
      }
    },
    {
      "replyToken": "8cf9239d56244f4197887e939187e19e",
      "type": "follow",
      "mode": "active",
      "timestamp": 1462629479859,
      "source": {
        "type": "user",
        "userId": "U4af4980629..."
      }
    }
  ]
}

基本的には、

  • ユーザ識別子 : e.events.source.userID
  • メッセージ : e.events.message.text

あたりを抑えておくと良い

各やりとりにおけるユーザ操作を考える

botにメッセージを送るやり方はいくつかあるので、チョイス。
細かくはTips集に記載。

  • テキスト入力
  • リッチメニューから選択
  • クイックリプライから選択
  • テンプレートメッセージから選択

(参考)リッチメニュー・メッセージタイプについて

Tips集

Tips1:複数"やりとり"まとめて1処理の実装

LINE MESSAGING API は基本的に1メッセージに対して、1処理のため、
例2・例3のような"従前の会話を踏まえた処理"は、自作が必要

  • 解決策の例:前回のやりとりをDBに保存
    • 一番最初に前回やりとりを確認する処理を入れる
    • 前回やりとりの結果を元に受け取った内容を処理

Tips2:bot環境は本番/開発の二つを用意

  • 理由

    • 開発用があったほうが機能追加/修正時に便利なため
    • むしろ、開発用ないととてもじゃないけど、修正ができないため
  • 実装のポイント

    • 開発/本番は、基本ソースは同じ
    • アクセストークン(=APIキー)を本番/開発で書き分けるだけにする
  • 注意点

    • アクセストークンを修正し忘れるとbotが何も機能しなくなる
    • デプロイ後は必ず基本的な動きを確認

Tips3:テキスト入力は最小限

  • ユーザ操作の"起点"は、リッチメニューで選択

  • "やりとり"は、クイックリプライ or テンプレートメッセージにする

  • 理由・メリット

    • 直感的で分かりやすいユーザビリティになる
    • 一連の"やりとり"において、エラーになりづらい

=== 「投資王」での例:買う操作 ===

例:リッチメニューから選択させる

例:やりとりは基本的にクイックリプライを活用

Tips4:PC版のことは考えない

  • 理由:PC版では以下の機能が使えないため
    • リッチメニュー
    • クイックリプライ

→ 結局テキストベースとなってしまうため、設計も面倒かつ使いづらいbotになる

Tips5:メッセージタイプを使い分ける

  • クイックリプライの特色を理解する

    • "やりとり"を見つつ、選択肢型でリプライができる
    • 表示領域が限定的
  • クイックリプライの実装は、以下を心がける

    • 選択肢の数を少なくする
    • 選択肢自体の文字数も少なくする
  • 逆に、選択肢が多い/選択肢の文字数が多い時は、テンプレートメッセージ

  • よくない例:「投資王」の商品選択
    →実際は選択肢が8つもあるのだが、3つしか画面上表示されていない
    (※ちなみに、今のところ直すつもりはない)

Tips6:リッチメニューには 「キャンセル」・「ヘルプ」 を

  • 実際にこうしたボタンを設けるに至った友人の声
    • キャンセルボタン
      • ユーザがメニューを2回タップしてしまったことによって、エラーが発生
      • 今どの部分のやりとりなのかわからなくなる
    • ヘルプボタン
      • 名前入力のやり方がわからず、登録を諦める

Tips7:登録時あいさつメッセージに「ヘルプ」を

  • 登録時あいさつメッセージとは
    • botを友達追加した時に、bot側からユーザに自動配信されるメッセージ
    • そのメッセージにヘルプページにリンクを貼っておく