Cloud Functions -Golang- でLINE Botを作る

Hiroki Kojima
Eureka Engineering
Published in
10 min readJun 30, 2019
Gopher by Takuya Ueda
The Gopher character is based on the Go mascot designed by Renée French.

こんにちは。エウレカAPIチームのコジマ (@__bsoo)です。
今回はGoogle Cloud FunctionsでLINE Messaging APIを利用して、メッセージを送ると固定メッセージを返してくれるところまでbotを作ってみたので、手順の記録と共にポイントを説明していこうと思います。

今回作成したレポジトリ: https://github.com/bsoo/gcf-line-bot-sample

やること

  • gcloudの設定
  • LINE Messaging APIの利用設定
  • Golangで実装
  • Cloud KMS でAPI keyを暗号化
  • Cloud Functionsにデプロイ

□ gcloud コマンドラインツール

はじめに gcloud コマンドラインツールをインストールや コンポーネントのインストール、プロジェクトの設定が必要です。
こちらを参考に設定をしてください。

□ LINE Messaging APIの利用設定

LINEのAPIを利用するために開発者登録、アプリの登録、tokenの発行などを行います。

開発者登録

LINEのアカウントでログインすることで、LINE開発者サイトアカウントが登録されます。

チャネル・プロバイダーの作成

公式のドキュメントに従ってチャンネル・プロバイダーの作成を行ってください。
作成が完了したらコンソールから作成したプロバイダー→チャネルを選択しチャネルの基本設定画面を開きます。

チャネルの基本設定画面

基本設定を開いたら「メッセージ送受信設定」のアクセストークン(ロングターム)の欄にある発行ボタンを押してアクセストークンを発行します。
次に同じページにある「LINE@機能の利用」の欄の自動応答メッセージをOffにします。右側にある「設定はこちら」のリンクから設定画面に移動し、応答メッセージをOffに切り替えてください。

□ 実装

任意の場所にプロジェクトディレクトリを作成します。

mkdir gcf-line-bot-sample
cd gcf-line-bot-sample

続いて以下のファイルをディレクトリに作成していきます。

webhook.go

○初期化

Cloud Functionsでもinit関数やグローバル変数を使う事でインスタンス単位ではリソースを使い回すことができるので、毎リクエスト毎に必要のないものはグローバルで持つなどすることで処理速度が大幅に改善できるかもしれません。

参考: Go ランタイム

○依存関係

Cloud FunctionsのGoのversionは1.11がサポートされています。ライブラリの管理にはgo moduleを利用するか vendor以下にまとめるかどちらかを選べます。 今回は go moduleを利用しています。
参考: Cloud Functions Go での依存関係の指定

○LINE Messaging API

LINEのMessaging APIはLINEさんが公式で出しているGoクライアントライブラリを利用しています。 リクエストの構造体が用意されているのでhttp.RequestをそのままParseRequestへと渡すだけで値を簡単に取得できます。Webhookからの通信を保証するための署名の検証もParseRequest内で行ってくれています。
イベントの種類も今回は単純にメッセージ受けたらテキストを返すだけなので単純なメッセージイベント(linebot.EventTypeMessage)しかハンドリングしていませんが、グループへの参加退出イベントや、LINE Beaconデバイスの受信圏をユーザーが出入りしたことを示すイベントなどちょっと面白いイベントも取れるようです。

参考

○KMS

暗号化の手順で再度でてきますが、API keyをまとめて暗号化した secrets.json.encファイルのデータを読み込み復号し、LINEのAPIのKeyとして使用できるようにしています。

参考: https://cloud.google.com/kms/docs/encrypt-decrypt?hl=ja

□その他に必要なファイル

go.mod, go.sum

webhook.goを配置したら以下のコマンドを実行して go.mod, go.sumを作成します。

$ export GO111MODULE=on; go build . 
$ cat go.mod
module github.com/bsoo/gcf-line-bot-samplego 1.11require (
cloud.google.com/go v0.40.0
github.com/line/line-bot-sdk-go v6.3.0+incompatible
google.golang.org/genproto v0.0.0-20190627203621-eb59cef1c072
)

secrets.json

{
"line_channel_secret": "your_line_channel_secret",
"line_channel_access_token": "your_line_channel_access_token"
}

↑の値はLINEのチャネルの基本設定画面にあるChannel Secretと、先程発行したアクセストークン(ロングターム)を設定してください。

.gcloudignore

Cloud Functionsにデプロイする際にディレクトリのファイルすべてアップロードしてしまうので不要なものはここに設定します。

.gcloudignore
.git
.gitignore
node_modules
secrets.json

□ API Keyの暗号化

secrets.jsonの内容を暗号化します。暗号化にはKMSを利用します。

  • キーリングを作成
$ gcloud kms keyrings create 【keyring_name】 \
--location global
  • キーリングに紐づく鍵を作成
    【keyring_name】【key_name】は任意のもので構いません。
$ gcloud kms keys create 【key_name】 \
--location global \
--keyring 【keyring_name】 \
--purpose encryption

これでsecret.jsonを暗号化するための鍵が作成されました。

では鍵を使ってsecret.jsonを暗号化します。
【keyring_name】【key_name】は先程と同じものを入力してください

$ gcloud kms encrypt \
--plaintext-file=secrets.json \
--ciphertext-file=secrets.json.enc \
--location=global \
--keyring=【keyring_name】 \
--key=【key_name】

成功すれば secrets.json.enc が作成され中に暗号化された文字列が入っています。

続いてCloud FunctionsでAPI Keyの復号を行うための権限設定を行います。

GCPコンソールから秘密鍵のページを開き、先程作成したキーリングを選択し、右側の欄にあるメンバーを追加を押し、新しいメンバーの欄に

【PROJECT_ID】@appspot.gserviceaccount.com

を入力し、役割から「クラウドKMSの暗号鍵の復号化」を選択して保存します。

参考: Cloud Functions アクセス制限

□ デプロイ

Cloud Functionsへデプロイを行います。

$ gcloud fucntions deploy 【function】 \
--runtime=go111 \
--trigger-http \
--entry-point=Webhook \
--set-env-vars="GCP_PROJECT_ID"="【gcp_project_id】","KMS_KEY_RING_NAME"="【keyring_name】","KMS_LINE_SECRETS_KEY_NAME"="【key_name】"

【function_name】は関数にの名前、【gcp_project_id】はGCPのプロジェクトIDを、【keyring_name】【key_name】は先程と同じものを入力してください。

30秒〜1分位でデプロイが完了します。以下のような表示がでたら成功です。
結果表示のhttpsTriggerの部分に書いてあるURLがAPIの接続先です。
また、serviceAccountEmailにでてくるメールアドレスも後ほど使用するのでメモしておいてください。

Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
entryPoint: Webhook
httpsTrigger:
url: 【url】
-- 【略】 -- timeout: 60s
updateTime: '2019-06-30T04:35:25Z'
versionId: '1'

このURLをWebhookのURLとして登録します。
再度LINEのチャネル基本設定ページを開き、「メッセージ送受信設定」にあるWebhook送信を「利用する」に変更します。そしてその下にあるWebhook URLに先程のURLを設定してください。その後「接続確認」のボタンが表示され、「成功しました。」と表示されれば完了です。

□ LINEで動作確認

これで準備ができました。最後に動作確認です。チャネル基本設定のBot情報にああるIDまたはQRから友達登録ができます。
そのままトーク画面に進みメッセージを送ってみて返ってくれば完了です。

□ 最後に

簡単なBotを作るならCloud Functionsはやはり簡単でおすすめです。ただしCloud Functionsまだbeta版なので扱いには注意が必要です。完成版が待ち遠しいです。

KMS周りはちょっと複雑なのと案外情報が少なく、そのままAPI keyは暗号化せずに環境変数から読み込んでいる例が多かったので、今回みたいな簡単にテストしたいくらいのbotならそのままでも良いかもしれません。

LINE API初めて触ったのですが、公式のGoクライアントが使いおかげで実装がとても簡単でした。今回もメッセージを送るだけだったりまだ触りきれていないのでもっと色々触ってみようと思います。

弊社では月に一回Goモクモク会を開催しています。もちろんCloud Functionsでなにかやるでも歓迎ですので、少しでも興味がある方お待ちしております。 Goもくもく会(ごもくかい)#17

--

--

Hiroki Kojima
Eureka Engineering

2014年に株式会社エウレカに新卒として入社。 現在はAPIチームに所属し、Pairsのバックエンド開発を担当。検索周りの機能をメインに担当しています。