🗒

【LINE Bot開発】チートシート for Node-RED × LINE Messaging API

2021/08/01に公開

前提

環境

  • この記事はNode-RED上でLINE Bot開発をするときの様々なパターンを解説する記事です。
  • LINE Messaging APIとの接続は次のノードを別途インストールして使う前提で書いています。

https://flows.nodered.org/node/node-red-contrib-line-messaging-api

設定

  • あらかじめLINE公式アカウントが作成済みであること
  • Botにする対象のLINE公式アカウントと友達になっていること
  • Botモードが有効であること(LINE公式アカウントマネージャー > 応答設定)
  • Webhookが有効であること(LINE公式アカウントマネージャー > 応答設定)
  • チャネルシークレットを取得済みであること(LINE Developers > チャネル基本設定)
  • チャネルアクセストークンの発行・取得済みであること(LINE Developers > Messaging API設定)
  • Webhook URLは「(自分のNode-REDホストのURL) /webhook」という形式で設定済みであること((LINE Developers > Messaging API設定))

友達全員に送りたいとき

※編集中

特定のユーザー(自分だけ)に送りたいとき

※編集中

ユーザーからのメッセージに返信したいとき

1. 基本形(オウム返し)

http in ノードと ReplyMessage ノードの2つが最小構成となります。

1-a. http in ノード

設定

必ずPOST形式で受け付けるようにしてください。

出力される msg.payload の中身

ユーザーからメッセージを受信したときに動作し、以下の msg.payload を出力します。
この内容はLINE Messaging APIの「Webhookイベントオブジェクト」に準拠するものです。

https://developers.line.biz/ja/reference/messaging-api/#webhook-event-objects

msg.payload
{
    "destination": "U70dc61fe94897194712970606c1230cc",
    "events": [
        {
            "type": "message",
            "message": {
                "type": "text",
                "id": "14487099500750",
                "text": "これはユーザーからのメッセージです"
            },
            "timestamp": 1627671638403,
            "source": {
                "type": "user",
                "userId": "Uc5c5892088deb5c1a7b04fc24b7022ed"
            },
            "replyToken": "0c9fa91c72ad4e25a15584ba41410f82",
            "mode": "active"
        }
    ]
}
ユーザーからのメッセージを取り出すには?

msg.payload.events[0].message.text に入っています。

1-b. ReplyMessage ノード

設定

チャネルシークレットとチャネルアクセストークンは必須です。
ReplyMessage欄は基本空欄です。常に固定メッセージを送りたい場合のみ入力してください。

入力すべき msg.payload の中身

以下の内容の msg.payload が必要です。(テキスト送信の場合)

msg.payload
{
    "events": [
        {
            "type": "message",
            "message": {
                "type": "text",
                "text": "ここにいれたメッセージがユーザーに送られます"
            },
            "replyToken": "(http inで受け取ったリプライトークン文字列・必須)",
        }
    ]
}

2. ユーザーメッセージをテンプレートに含めて返信

http in ノード および ReplyMessage ノードは 1.基本形 と同じです。

2-a. template ノード

設定

  • Property(結果をセットする位置)は msg.payload.events[0].message.text にします。
  • テンプレート内でユーザーから送信された文字列を表示するには {{ msg.payload.events.0.message.text }} を用います。

3. ユーザーメッセージを加工して返信

先頭の http in ノード および末尾の ReplyMessage ノードは「1.基本形」と同じです。

http in ノードから出力される msg.payload の内部には、LINEで最終的に「返信」の動作を行う際に必須となる情報(どのメッセージに返信するのかを示すIDなど)が含まれるため、最終の ReplyMessage ノードまで情報を保持する必要があります。したがって、次のような仕組みでLINE情報の保持と通常のpayload利用を両立させています。

  1. function 1 ノード内でその必須となる情報を msg.line に退避させます。
  2. 中間のノードで自由に文字列加工等を行います。複数のノードでも問題ありません。
  3. function 2 ノード内で msg.line に退避させておいた情報を msg.payload に復元したうえで、返信したいメッセージを msg.payload.events[0].message.text に再設定(もししなければユーザーが送った文字列のまま)しています。

3-a. function 1 ノード

ソースコード
// LINEサーバーからの情報をmsg.lineに退避させる
msg.line = msg.payload;

// msg.payloadに送信されたメッセージ本体を入れる
msg.payload = msg.payload.events[0].message.text;

return msg;

3-b. 文字列加工 ノード

図では function ノードを使っていますが、入力、出力ともに msg.payload を使うもの(ほぼ全てでデフォルトですが)であればどんなノードでもかまいません。また、複数のノードの集合でもよいです。

3-c. function 2 ノード

ソースコード
// 送信したい文字列をresultに退避させておく
const result = msg.payload;

// LINEサーバーからの内容をpayloadに復元する
msg.payload = msg.line;

// 返信メッセージをhttp requestの結果にする
msg.payload.events[0].message.text = result;

return msg;

4. http request でAPIリクエスト結果を返信(APIパラメータなし)

「3. ユーザーメッセージを加工して返信」をベースに、中央の文字列加工をするノードを http request ノードに変更しているだけです。

4-a. http request ノード

設定

Returnの形式がUTF-8文字列とバイナリバッファの場合は、その内容がそのまま msg.payload に入ります。が、 文字列で複数のデータを得るAPIであればほとんどJSONオブジェクトです。この場合、まずこのノードの出力を debug ノードにつないで、その中身がどうなっているか確認しましょう。

4-b. function 2 ノード

設定(出力がJSONオブジェクトのときのみ)

まず http request ノードの直後に debug ノードを接続し、中身を確認しながら欲しいデータを探してみましょう。
例: Jikan API より
https://api.jikan.moe/v3/search/anime?q=jutsu&limit=10 へのリクエスト:

アニメタイトルを示す "Jujutsu Kaisen (TV)" という文字列が欲しい場合……
→「3-c. function 2 ノード」で示したソースコード2行目を以下のように変更したものを設定:

const result = msg.payload.results[7].title;

5. http request でAPIリクエスト結果を返信(GETメソッド・APIパラメータあり)

基本構成は「4. http request でAPIリクエスト結果を返信(APIパラメータなし)」と同じですが、function 1 ノードを書き換えてLINEからの文字列の一部がAPIのURL内に反映されるようにする必要があります。

5-a. http request ノード

例: Sunset and sunrise times API を使って
「2021年7月26日の、緯度35.70113度・経度139.76885度」を得たいとき……
→ アクセスすべきURLは以下の通りとなる:
https://api.sunrise-sunset.org/json?lat=35.70113&lng=139.76885&date=2021-07-26

このURLのうち ?lat=35.70113&lng=139.76885&date=2021-07-26 部分を、このノードの1つ手前である function 1 ノードから設定できるようにし、特に LINEで送った日付文字列をそのまま検索パラメータとして設定できるようにしてみます。

設定

5-b. function 1 ノード

ソースコード
// LINEサーバーからの情報をmsg.lineに退避させる
msg.line = msg.payload;

// msg.payload.dateに送信されたメッセージ本体(2021-07-26のような日付の形式を想定)を入れる
msg.payload.date = msg.payload.events[0].message.text;

// 緯度経度は固定値としてここで設定する
msg.payload.lat = 35.70113;
msg.payload.lng = 139.76885;

return msg;

6. http request でAPIリクエスト結果を返信(POSTメソッド・APIパラメータあり)

※編集中

Discussion