[API構築5] line-bot-sdk-goとngrokでchatbotを作る
概要
lineアプリからメッセージを送るとオウム返しで返答を行うbotサーバを作成する。
ローカルにbotサーバを作り、lineの設定を行ってlineアプリへの返答をbotサーバが行うようにする。
botサーバの作成
ローカルにlineからのwebhookを受けてリプライを返すbotサーバを作成する。
line-bot-sdk-go
line-bot-sdk-goはgoでlinebotを作成しやすくするためのもの。
LINE Messaging API SDK for Go を使用すると、LINE Messaging API を使用したボットの開発が簡単になり、数分でサンプルボットを作成できます。
本来lineのbot作成はmessaging APIを利用するためAPIを作成しwebhookを設定するという手順を踏むが、LINEはこれを各言語で簡単に実装するSDKを作成する。line-bot-sdk-goはそれのgo版。
今回はこれを利用してオウム返しをするlinebotを作成する。
line-bot-sdk-goの導入
line-bot-sdk-goのgithubのREADMEを参考に導入する。
go get -u github.com/line/line-bot-sdk-go/v7/linebot
サーバプログラムを書く
以下の機能を持つプログラムを書きます。
API名 | パス | HTTPメソッド | 説明 |
---|---|---|---|
動作確認API | / | GET | 動作確認用にブラウザでGETで固定値「hello workd」を返すAPI |
LINEチャットbotリプライAPI | /callback | POST | LINEアプリからの返答に対するリプライを行うAPI |
コード
package main
import (
"fmt"
"net/http"
"os"
"github.com/gin-gonic/gin"
"github.com/line/line-bot-sdk-go/v7/linebot"
)
func main() {
engine := gin.Default()
engine.GET("/", getTop)
engine.POST("/callback", postCallback)
engine.Run(":" + os.Getenv("PORT"))
}
func getTop(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "hello world",
})
}
func postCallback(c *gin.Context) {
// bot作成
bot, err := linebot.New(
os.Getenv("CHANNEL_SECRET"),
os.Getenv("CHANNEL_TOKEN"),
)
if err != nil {
fmt.Println(err.Error())
return
}
// リクエスト処理
events, berr := bot.ParseRequest(c.Request)
if berr != nil {
fmt.Println(berr.Error())
return
}
for _, event := range events {
if event.Type == linebot.EventTypeMessage {
switch message := event.Message.(type) {
case *linebot.TextMessage:
_, rerr := bot.ReplyMessage(
event.ReplyToken,
linebot.NewTextMessage(getResMessage(message.Text)),
).Do()
if rerr != nil {
fmt.Println(rerr.Error())
}
}
}
}
}
func getResMessage(message string) string {
return "あなたは" + message + "と言いました。"
}
参考にしたline-bot-sdk-goのサンプル
(ginの書き方についてはもう少し進めてから改めて勉強しなおす)
実行
export PORT=8080
export CHANNEL_TOKEN=<トークン>
export CHANNEL_SECRET=<シークレット>
go run api/main.go
動作確認
ブラウザから確認APIへアクセスし返答がくることを確認した。
botサーバを外部公開する(httpsとドメインを用意する)
LINEアプリからのメッセージを受け取るにはLINEがbotサーバにアクセスできるよう、botサーバのhtpsのドメインをLINE Developersに登録する必要がある。
しかし開発環境を整えるためだけに本番環境構築であるドメインの発行とhttpsの設定をするのはスマートではない。
なのでここではローカルのサーバをお手軽に外部公開(httpsとドメインの付与)ができるngrokを利用する。
ngrokのインストール
brew install ngrok
ngrokの実行
ngrok http 8080
ngrok (Ctrl+C to quit)
🤯 Try the ngrok Kubernetes Ingress Controller: https://ngrok.com/s/k8s-ingress
Session Status online
Session Expires 1 hour, 59 minutes
Terms of Service https://ngrok.com/tos
Version 3.3.1
Region Japan (jp)
Latency 24ms
Web Interface http://127.0.0.1:4040
Forwarding https://88f6-2407-c800-1f11-777-adb4-51c1-c926-e461.ngrok.io -> http://localhost:8080
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
実行のたびにlocalhost:8080に接続するURLを払い出してくれる。
動作確認
ブラウザからngrok経由で確認APIへアクセスし返答を確認した。
LINE DevelopersのWebhookURLの設定
作成したhttps://88f6-2407-c800-1f11-777-adb4-51c1-c926-e461.ngrok.io/callback
をLINE DevelopersコンソールのWebhookURLに設定する。(画像だと4f65から始まるURLになっているが、このあと88f6のものを設定している。)
Webhookの利用をONにする。
「検証」ボタンを押し、成功と出ればOK。
LINEアプリから動作確認する
LINE アプリからメッセージを送り、返答されるか確認する。
LINE DevelopersコンソールのMessageAPI設定のQRコードをスマホで読み込み、LINEアプリでメッセージを送る。返答が来た。成功。
所感
ngrokがめちゃくちゃ便利。複雑な設定なしの1コマンドで実行できるのが大変ありがたい。
line-bot-sdk-goがとても便利。APIだけでやろうとすると、post APIへの返答は200のみで、リプライは別APIでこちらからコールする仕組みのため少々面倒だが、これを直感的にコーディングできるのはとても良い。
注意点として、SDKのREADMEにあるドキュメントリンクがmessaging APIへのリンクになっているので、SDK自体の詳細ドキュメントは存在せず、詳細仕様が知りたければmessage APIのリファレンスから推測するしかなさそう。それで十分だと良いが。コード読めってことか。。。
また、SDKサンプルでは受け取ったPOST APIアクセスに対してすぐにbot.ReplyMessage.Do()
を行っているが、messaging-apiのリファレンスでHTTP POSTリクエスト処理を非同期化することを推奨している(※参考画像)ことから、LINEとしてはPOST APIアクセスとリプライを非同期処理にすることを推奨している気がする。ボットのリクエスト数や処理が増えたら非同期化を検討する。goroutineでの並行処理は好きなので楽しみ。
※参考画像
参考
Discussion