🐕

[API構築5] line-bot-sdk-goとngrokでchatbotを作る

2023/07/18に公開

概要

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を作成する。

https://github.com/line/line-bot-sdk-go

https://developers.line.biz/ja/docs/messaging-api/overview/

https://developers.line.biz/ja/reference/messaging-api/

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のサンプル
https://github.com/line/line-bot-sdk-go/blob/master/examples/echo_bot/server.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を利用する。

https://qiita.com/mininobu/items/b45dbc70faedf30f484e

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/callbackLINE 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での並行処理は好きなので楽しみ。

※参考画像

https://developers.line.biz/ja/reference/messaging-api/

参考

https://qiita.com/Aki_Mineo/items/941dbd722e9d1754308d

GitHubで編集を提案

Discussion