Netlify FunctionsでLINE BOTを作ってみる


Netlify FunctionsはAWS Lambda上で動作するNode.js環境です。最近のnowとかに似てる雰囲気ですね。

ある程度無料でNode.jsがホスティングできる環境っぽい雰囲気で覚えておくと良いかもしれません。

ちなみに今日は東京ハッカソン@ヒーローズ・リーグ 2019 by MAのハッカソン会場からです。 #ヒーローズリーグ

Netlify Functionsでのハローワールド

【入門】Netlify Functionsコトハジメなどの記事を見るとハローワールドが出来ます。

プロジェクトルートにnetlify.tomlを追加

まずは、通常のNode.jsプロジェクトを作ります。

$ mkdir mylinebot
$ cd mylinebot
$ npm init -y

package.jsonが作成されます。
このプロジェクトのルートにnetlify.tomlを作成します。

netlify.toml
[build]
  command = "npm run build"
  functions = "dist/api"

必要なモジュールを追加

$ npm i express @line/bot-sdk serverless-http netlify-lambda

ミニマムでハローワールドを試すならnetlify-lambdaだけで問題ないですが、後の手順のためにLINE BOTのSDKやexpress、serverless-httpも入れておきます。

任意のフォルダにJSファイルを設置

今回はsrcフォルダを作成して、その中にserver.jsを設置します。

package.jsonscriptsの箇所に起動スクリプトを記述します。

  "scripts": {
    "dev": "netlify-lambda serve ./src",
    "build": "netlify-lambda build ./src"
  },

今回はsrcフォルダですが"netlify-lambda serve <任意フォルダ>"という形になります。

hello.js

srcフォルダにhello.jsを作成します。

src/hello.js
exports.handler = function(event, context, callback) {
    callback(null, {
        statusCode: 200,
        body: `Hello, World`
    });
}

ローカル起動

$ npm run dev

これでhttp://localhost:9000/.netlify/functions/helloにアクセスするとHello, Worldが表示されます。

/.netlify/functions/<ファイル名>というアクセス方法になるらしく、今回はhello.jsとしたのでこのようなURLでのアクセスになりました。

http://localhost:9000/helloみたいなアクセス方法って出来ないのかな......?

デプロイして確認

GitLabやGitHubにデプロイして、Netlifyとリポジトリを連携すればOKです。

https://xxxxxxxxxxxxxxxxx.netlify.com/.netlify/functions/helloにアセクスするとHello, Worldが表示されるはずです。

LINE BOTを作成する

ここからLINE BOT作成ですが、基本は1時間でLINE BOTを作るハンズオンのコードをベースにして作っていきます。

  • LINE BOTの基礎
  • ngrokの使い方

を事前に把握しておきましょう。

Netlify Functionsでexpressを扱うサンプル

通常のExpressのコードをそのまま利用することが出来ないため、元のソースコードを改変します。

neverendingqs/netlify-expressが参考になりました。

依存モジュール

↑でインストールしていれば問題ないです。

$ npm i express @line/bot-sdk serverless-http netlify-lambda

おうむ返しLINE BOTのコード

↑で作成したsrcフォルダにserver.jsを作成します。

src/server.js
'use strict'

const express = require('express');
const line = require('@line/bot-sdk');
const serverless = require('serverless-http'); //追加
const app = express();

const config = {
    channelSecret: 'チャンネルシークレット',
    channelAccessToken: 'チャンネルアクセストークン'
};

const router = express.Router(); //ルーティング用に追加
router.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用(無くても問題ない)
router.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);

    //ここのif分はdeveloper consoleの"接続確認"用なので削除して問題ないです。
    if(req.body.events[0].replyToken === '00000000000000000000000000000000' && req.body.events[1].replyToken === 'ffffffffffffffffffffffffffffffff'){
        res.send('Hello LINE BOT!(POST)');
        console.log('疎通確認用');
        return; 
    }

    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});

const client = new line.Client(config);
function handleEvent(event) {
    if (event.type !== 'message' || event.message.type !== 'text') {
      return Promise.resolve(null);
    }

    return client.replyMessage(event.replyToken,{
      type: 'text',
      text: event.message.text
    });
}

app.use('/.netlify/functions/server', router); //ルーティング追加
module.exports = app; //追加
module.exports.handler = serverless(app); //追加

ローカルで試す

$ npm run dev

これでlocalhostの9000番ポートで起動します。

$ ngrok http 9000

これでngrok側で発行されたURLをLINE Developers側に登録して動作確認してみましょう。

LINE BOTの設定

今回ngrokのアドレスが7db932fe.ngrok.ioで生成されたので以下のようなパスをLINE DevelopersのBOTのWebhookの設定に書いてあげます。

ローカルでの確認が終わったら、デプロイしてhttps://xxxxxxxxxxxxxxxx.netlify.com/.netlify/functions/server/webhookなどのデプロイ後のURLを登録し直しましょう。

これでBOTが永続かできます。

試してみる

ちゃんとおうむ返しをしてくれているので問題なく動いてそうです。

GitHubにあげておきました。

完成版っぽいサンプルです。

最終的にはdotenv使ってます。

まとめ

まだまだドキュメントやサンプルが少ない印象だけど、無料で結構使える模様なので、個人制作のサービスや、ハッカソンなどで作ったものをお金書けずに置いておくとかの場合に使えそうです。

課金すればもっと色々やれるっぽいですが、とりあえずは無料FaaSの選択肢の一個として頭に入れておくと良いかもしれません。

おまけ

Netlify Functionsで謎のデプロイの失敗がありました。

Deployのログを見るとfailed during stage 'deploying site': Failed to execute deploy~~みたいな感じで、調べるとNetlifyでfunctionsのデプロイがなぜか失敗する時の対処法などの記事が。

待とう。何かNetlifyの機嫌が悪いだけかもしれない。もしくはアカウントやプロジェクトを作ったばかりの時はLambda側の連携の準備ができていないのかもしれない。

僕の場合は何時間かたって再度Retryしてみたらデプロイができた。

ただ、元々成功していたプロジェクトのデプロイが急にできなくなったのであれば、違う原因かもしれないので注意。エラーメッセージを要確認。

ということで、原因はよくわからないけど時間が解決したという話があったので、一回Netlify上でアプリを削除して再度デプロイしたら特に問題なくデプロイできるようになりました。

なんだったのか。

デプロイについて: 2020年9月17追記

久々に自分の記事を見たらデプロイについて特に記載がなかったので追記。

ローカルで作ったプロジェクトをGitHubやGitLabなどにあげて、NetlifyでGitリポジトリと連携させてアプリケーション作成し、pushすればOKです。

Netlifyの管理画面に表示されるhttps://xxxxxxxxx.netlify.appというドメインの後ろに/.netlify/functions/server/webhookというパスをつけたURLが最終的なURLになります。

デプロイ後はこちらのURLをLINE BOTと紐付けましょう。

参考記事