これはfukuoka.ex Elixir/Phoenix Advent Calendar 2019の13日の記事です。 ElixirでLineのチャットボットを作る方法を紹介します。 🧪🤖🧪
昨日はsanpo_shihoさんの「Rails経験者に贈るPhoenix入門」でした。
-
先ずはLine Developers ConsoleにMessaging API Channelを作成する必要があります。 そして作成されたチャネルIDとチャネルシークレットを後で使用するためメモしておき、ボットと友達になります。
-
Supervision treeありのElixirのアプリを作ります。
mix new advent --sup
-
cd advent
-
gitを使いたい場合はリポジトリを作ります(任意):
git init && git add . && git commit -m 'Initial commit'
このガイドで今後gitについては話しません。
-
アプリが動いているかを確認します:
$ iex -S mix Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [hipe] Interactive Elixir (1.9.2) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> Advent.hello :world
-
line_bot
とその他必要なライブラリーをmix.exs
に追加しますdefp deps do [ {:line_bot, "~> 0.1.0"}, {:plug_cowboy, "~> 2.0"} ] end
-
mix deps.get
でline_bot
のパッケージをフェッチします。 -
config/config.exs
でコンフィグファイルをを作ります。import Config config :line_bot, client_id: "YOUR_CLIENT_ID", client_secret: "YOUR_CLIENT_SECRET", # TODO remove this before deployment! skip_validation: true
client_id
とclient_secret
は上記でメモしておいたLine Developer ConsoleのチャネルIDとチャネルシークレットです。 -
:advent
と:line_bot
のエリクサーのアプリが自動的に開始されることを確認します。$ iex -S mix Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [hipe] Interactive Elixir (1.9.2) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> Application.started_applications [ {:advent, 'advent', '0.1.0'}, {:line_bot, 'A package for creating chatbots with the Line messenger', '0.1.0'}, ...
-
Lineサーバーのwebhookのrequestに対応できるようにするため、
lib/advent/router.ex
にPlugのrouterを書きます。defmodule Advent.Router do use Plug.Router plug :match plug :dispatch forward "/bot", to: LineBot.Webhook, callback: Advent end
-
Routerを開始するために
lib/advent/application.ex
に以下を設定します。children = [ Plug.Cowboy.child_spec(scheme: :http, plug: Advent.Router, options: [port: 4000]) ]
-
iex -S mix
でアプリを再起動して、テストリクエストに反応があるかどうかを確認します。curl http://localhost:4000/bot
以下の通りに出力されること。
19:31:18.051 [warn] Skipping signature validation because :skip_validation is enabled. 19:31:18.051 [debug] Webhook Request:
今サーバーが動いていて、webhookのイベントを受け取っている状態です。インターネットに接続しましょう。
-
Lineサーバーのリクエストをローカル環境に届けるために、ngrokというHTTPSのproxyが便利です。 ポート4000で起動してください。
$ ngrok http 4000 ngrok by @inconshreveable (Ctrl+C to quit) Session Status online Account Adam Millerchip (Plan: Free) Version 2.3.35 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://xxxxxxxx.ngrok.io -> http://localhost:4000 Forwarding https://xxxxxxxx.ngrok.io -> http://localhost:4000
-
ngrokが出力したURLの末尾に
/bot
を追加して、https://xxxxxxxx.ngrok.io/bot
をLine Developer ConsoleのWebhook URLに貼り付けてください。 -
それでは、ボットのコードを実装しましょう.
lib/advent.ex
を以下に書き換えます。defmodule Advent do use LineBot end
-
今、ボットがイベントに反応しているかどうかを確認できます。 ラインでチャットを開いてボットにメッセージを送ってください。 iexのコンソールに上記のメッセージに対するWebhook Requestが届くことを確認します。 例えば、「Hello, bot!」と送信した場合
19:34:48.510 [debug] Webhook Request: {"events":[{"type":"message","replyToken":"xxxxxxxxx","source":{"userId":"U123456789abcdefghijllmnopqrstuvw","type":"user"},"timestamp":1575801287666,"message":{"type":"text","id":"0","text":"Hello, Bot!"}}],"destination":"Uyyyyyyyyyy"}
-
ボットがメッセージに返信できるように実装しましょう。先ずは簡単にechoボットを実装します。
defmodule Advent do use LineBot def handle_message(%{"type" => "text", "text" => message}, _info, reply_token) do reply = %LineBot.Message.Text{text: message} LineBot.send_reply(reply_token, reply) end end
上手くいけば、ボットが送られたメッセージをそのまま返してくれます。
-
iexから直接メッセージを送信することができます。このボット用の自分のユーザーIDを確認してください。 Webhook Requestのログに記載があるはずです。自分に「Hello from iex!」とメッセージを送りましょう。
iex> me = "U123456789abcdefghijllmnopqrstuvw" "U123456789abcdefghijllmnopqrstuvw" iex> message = %LineBot.Message.Text{text: "Hello from iex!"} %LineBot.Message.Text{quickReply: nil, text: "Hello from iex!", type: :text} iex> LineBot.send_push(me, message) 19:55:02.919 [debug] API Response: %HTTPoison.Response{status_code: 200, request_url: "https://api.line.me/v2/bot/message/reply", ...} {:ok, %{}}
上手くいけば、ラインのトークに届きます。
-
開発しながら直接HTTP Requestをアプリに送信するのが便利ですが、ラインサーバーからのメッセージを受け取れる状況のため他人のサーバーから悪用できないように、ラインの証明書を確認する設定をしましょう。
config/config.exs
にimport Config config :line_bot, client_id: "YOUR_CLIENT_ID", client_secret: "YOUR_CLIENT_SECRET", skip_validation: false
これだけです!ラインサーバーからリクエストを受け取って返信するだけのシンプルなラインボットを作りました。 開発しながらコマンドラインから直接メッセージを送信する方法も紹介しました。
使用可能なAPIのコマンドと全ての対応できるイベントタイプはLineBot
に書いてあります.
全ての機能に対応してるサンプルアプリもあります。line_bot_sample.ex
をlib/advent.ex
にコピペして動かしてみませんか?