🤖

Cloudflare Workersでコピペだけで作れるLINE Bot

2024/08/07に公開

久しぶりのCloudflareのネタです。

Cloudflare Workersはちょこちょこハンズオンで触ってきましたが、LINE Botのようなシンプルなサーバーサイドアプリケーションと相性がいいと感じました。

というわけで今回はCloudflare Workersで動くLINE Botを構築していきます。

なお、LINE Developersのアカウント、及びCloudflareのアカウントをすでに作成している前提で進めます。

また、今回作ったサンプルコードは以下のリポジトリにも公開しています。

https://github.com/Miura55/cloudflare-line-echo-bot

事前準備

  • LINE Developersのアカウント
  • Cloudflareのアカウント
  • Node.js(v18以上)

LINE Messaging APIの設定

まずは、今回使用するMessaging APIの設定を行います。

以下のURLを参考にMessaging APIの設定を行います。

https://developers.line.biz/ja/docs/messaging-api/getting-started/#page-title

チャネルを作成したら、チャネルアクセストークンをメモしておきます。

Cloudflare WorkersでLINE Botを作成する

Wranglerのセットアップ

今回はCloudflare Workersのプロジェクトを作成するために、Wranglerを使います。

WranglerはCloudflare WorkersのCLIツールで、プロジェクトの作成、デプロイ、テストなどを行うことができます。

Wranglerは以下のコマンドでインストールします。

npm install -g wrangler

インストールしたら以下のコマンドでOAuth認証を行います。

wrangler login

これだけでCloudflare Workersのローカル開発環境が整いました。

プロジェクトの作成

続いて、今回のLINE Botのプロジェクトを作成します。

今回はプロジェクト名を cloudflare-line-echo-bot とし、以下のコマンドでプロジェクトを作成します。

wrangler init cloudflare-line-echo-bot

ここから対話形式で質問が出てきます。以下の質問が来たときには Hello World example を選択します。

What would you like to start with?

以下の質問が来たときには、 Hello World Worker を選択します。

Which template would you like to use?

最後に以下の質問が来たときには、 JavaScript を選択します。

Which language do you want to use?

以上の質問を回答すると、依存パッケージは必要なファイルが作成されます。

その後続けて Do you want to use git for version control? という質問が来ますが、これはソースコードをGit管理でしたいときには yes を選択します。

さらに Do you want to deploy your application? という質問が来たら、この後ソースコードを書いてからデプロイするので no を選択すれば問題ありません。

以上でプロジェクトの作成が完了しました。

作業ディレクトリの直下に cloudflare-line-echo-bot というディレクトリが今回のWorkersのプロジェクトは正常に作成されているはずです。

LINE Botの作成

それでは今回開発するLINE Botのソースコードを書いていきます。

cloudflare-line-echo-bot/src ディレクトリ内にある index.js を以下のように書き換えます。

/**
 * Cloudflare Workersで動くLINE Botのサンプル 
 *
 * - Run `npm run dev` in your terminal to start a development server
 * - Open a browser tab at http://localhost:8787/ to see your worker in action
 * - Run `npm run deploy` to publish your worker
 *
 * Learn more at https://developers.cloudflare.com/workers/
 */

const endpoint = "https://api.line.me/v2/bot/message/reply";

export default {
  async fetch(request, env) {
    /**
     * readRequestBody: リクエストボディを読み込む 
     * @param {Request} request the incoming request to read from
     */
    async function readRequestBody(request) {
      const contentType = request.headers.get("content-type");
      if (contentType.includes("application/json")) {
        const body = await request.json();
        return body;
      } else {
        return "Invalid content-type";
      }
    }

    /**
     * replyMessage: LINEにメッセージを返信する 
     * @param {string} replyToken the reply token to send back to LINE
     * @param {string} message the message to send back to LINE
     */
    async function replyMessage(replyToken, message) {
      const requestBody = JSON.stringify({
        replyToken: replyToken,
        messages: [
          {
            type: "text",
            text: message,
          },
        ],
      });

      const response = await fetch(endpoint, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${env.LINE_CHANNEL_ACCESS_TOKEN}`,
        },
        body: requestBody,
      });

      return response;
    }

    if (request.method === "POST") {
      const reqBody = await readRequestBody(request);
      console.log(`The request body sent in was ${JSON.stringify(reqBody)}`);

      if (reqBody.events) {
        for (const event of reqBody.events) {
          if (event.type === "message" && event.message.type === "text") {
            await replyMessage(event.replyToken, event.message.text);
          }
        }
      }
      return new Response('OK');
    } else if (request.method === "GET") {
      return new Response("OK");
    }
  },
};

このソースコードをコピペするだけで追加でモジュールをインストールすることなくオウム返しのLINE Botが作成できます。

環境変数の設定

Messaging APIのチャネルアクセストークンはソースコード内に直接書くのはセキュリティ上よくないので、環境変数として設定します。

Cloudflare Workersで環境変数を参照するときには以下の関数の引数 env でCloudflare上にあらかじめ設定された環境変数のオブジェクトを参照できます。

  async fetch(request, env) {
	...
  }

今回は環境変数として LINE_CHANNEL_ACCESS_TOKEN を設定し、コード上では env.LINE_CHANNEL_ACCESS_TOKEN で参照するようにしています。

参照した値は以下のBotでメッセージを返答する箇所で使用しています。

	  const response = await fetch(endpoint, {
		method: "POST",
		headers: {
		  "Content-Type": "application/json",
		  Authorization: `Bearer ${env.LINE_CHANNEL_ACCESS_TOKEN}`,
		},
		body: requestBody,
	  });

この環境変数もWranglerで設定することができます。

設定では以下のコマンドを実行することでシークレットな環境変数を設定するための対話形式のプロンプトが表示されます。

wrangler secret put LINE_CHANNEL_ACCESS_TOKEN

起動したプロンプトにMessaging APIのチャネルを作成したときにメモしたチャネルアクセストークンを入力します。

その後、以下のコマンドを実行してシークレットな環境変数が設定されているか確認します。

wrangler secret list

以下の事項結果が表示されれば環境変数の設定は完了です。実際のシークレットの値は伏せて表示されます。

[
  {
    "name": "LINE_CHANNEL_ACCESS_TOKEN",
    "type": "secret_text"
  }
]

デプロイ

これでデプロイに必要な準備が整いました。

wranglerでプロジェクトを作成した場合は、以下のコマンドを実行することでCloudflare Workersにデプロイすることができます。

npm run deploy

デプロイが完了すると、以下のようなメッセージが表示されます。

 ⛅️ wrangler 3.68.0 (update available 3.69.0)
-------------------------------------------------------

Total Upload: 1.51 KiB / gzip: 0.63 KiB
Worker Startup Time: 1 ms
Uploaded cloudflare-linebot (1.81 sec)
Published cloudflare-linebot (0.28 sec)
  https://cloudflare-linebot.xxxx.workers.dev

この中にある .workers.dev ドメインのURLがMessaging APIのチャネルの設定にあるWebhook URLに設定する値です。

LINE DevelopersのコンソールからMessaging APIのチャネルの設定を開き、Webhook URLにこのURLを設定します。

あとはLINE公式アカウントマネージャーからの応答メッセージを無効にしてWebhookを有効にすればLINE Botが完成です。

テキストのメッセージを送信すると以下の通り送信したメッセージが送信されることが確認できます。(途中何も返信ないのは環境変数の参照が失敗しているのが原因です…)

ちなみに今回のソースコードでは疎通確認用にGETリクエストを受け付けるようにしているので、ブラウザからアクセスすることで OK とレスポンスが返ってくることを確認できます。

おまけ(ローカルでの開発)

ローカルで開発をするときには環境変数の参照をするために、プロジェクトのディレクトリ直下に .dev.vars ファイルを作成し、以下のように環境変数を設定します。

LINE_CHANNEL_ACCESS_TOKEN="YOUR_CHANNEL_ACCESS_TOKEN"

作成したら以下のコマンドでローカルサーバーを起動します。

npm run dev

あとはngrokなどでポートを払い出したURLをWebhook URLに設定すれば、ローカル環境でデバッグができます。(同じCloudflare使っているなら Cloudflare Tunnel を使うのもありです)

LINE Developer Community

Discussion