前回
LINE WORKSのAPIを使うために必要な各種設定とTokenの発行までを行いました。
前回: https://qiita.com/mmclsntr/items/1d0f520f1df5dffea24b
今回は、実際のチャットボットの実装を行います。
LINE WORKS トークBotの仕組み
ユーザーからのメッセージを受信し、それに応じた返答を返すという対話を行うために、LINE WORKSでは トーク Bot API が用意されています。
トークBot APIの概要: https://developers.worksmobile.com/jp/document/3005001?lang=ja
メッセージ送受信用Webアプリケーションを用意し、LINE WORKS Developer Console上でBotにコールバックURLとして紐付けを行うことで、LINE WORKS上にチャットボットを実装することができます。
今回は、PythonとAWS Lambdaを使って開発したいと思います。
検証環境
言語: Python 3.7
実行環境: AWS Lambda
今回は、AWS API Gateway + Lambdaの構成で作りました。
1. チャットボット開発
1.1. リクエスト検証
コールバックに設定したサーバーに送られて来たリクエストが正しいものであるか、その確認をする仕組みが用意されています。
https://developers.worksmobile.com/jp/document/1005009?lang=ja
以下、コードサンプル。
import os
from base64 import b64encode, b64decode
import hashlib
import hmac
API_ID = os.environ.get("API_ID") # API ID
def validate_request(body, signature):
"""
リクエスト検証
"""
# API IDを秘密鍵に利用
secretKey = API_ID.encode()
payload = body.encode()
# HMAC-SHA256 アルゴリズムでエンコード
encoded_body = hmac.new(secretKey, payload, hashlib.sha256).digest()
# BASE64 エンコード
encoded_b64_body = b64encode(encoded_body).decode()
# 比較
return encoded_b64_body == signature
1.2. メッセージの受信
送られてくるメッセージのタイプは大きく分けて5つあります。
タイプ | 説明 |
---|---|
message | 一般メッセージ。 |
join | Bot を複数人トークルームに招待。 |
leave | Bot が複数人トークルームから退室。 |
joined | メンバーが Bot の属するトークルームに参加。 |
left | メンバーが Bot の属するトークルームから退室。 |
特に、message
には、下の4タイプあります。
メッセージタイプ | 内容 |
---|---|
text | テキスト |
location | 位置情報 |
sticker | スタンプ |
image | 画像 |
LINEと同じくスタンプメッセージにも対応してます。
メッセージ受信 - Callback 形式: https://developers.worksmobile.com/jp/document/1005009?lang=ja
1.3. 返答メッセージ返答
返答メッセージを送るために、メッセージ送信用のAPIを使います。
メッセージ送信: https://developers.worksmobile.com/jp/document/1005008?lang=ja
これは、リプライだけでなくプッシュ通知を行う際も使われます。
このAPIを利用する際に、前回発行したTokenを利用します。
送信できるメッセージのタイプは以下の通り。
メッセージタイプ | 内容 |
---|---|
text | テキスト |
image | 画像 |
link | リンク |
buttonTemplate | ボタンテンプレート |
listTemplate | リストテンプレート |
sticker | スタンプ |
以下、コードサンプル。
import os
import json
import requests
import urllib
API_ID = os.environ.get("API_ID") # API ID
SERVER_API_CONSUMER_KEY = os.environ.get("SERVER_API_CONSUMER_KEY") # Server API Consumer Key
BOTNO = os.environ.get("BOTNO") # Bot No
TOKEN = os.environ.get("LW_TOKEN") # 発行したToken
def send_message(content, account_id):
"""
送信
"""
url = 'https://apis.worksmobile.com/' + API_ID + '/message/sendMessage/v2'
headers = {
'Content-Type' : 'application/json;charset=UTF-8',
'consumerKey' : SERVER_API_CONSUMER_KEY,
'Authorization' : "Bearer " + TOKEN
}
params = {
"botNo" : int(BOTNO),
"accountId" : account_id,
"content" : content
}
form_data = json.dumps(params)
r = requests.post(url=url, data=form_data, headers=headers)
if r.status_code == 200:
return True
return False
※ 注意
メンバー数によってクォータ(最大送信数の制限)が設定されています。
メンバー数が 100 人以下 : 最大 20,000 回 / 日
メンバー数が 100 人超過 : 最大 20,000 回 + (超過するメンバー数)*100 回 / 日
クォータは 0 時(GMT +9)にリセットされます。
クォータの 80%、90%、100% に到達すると、管理者に通知メールを送信します。
1.4. コード全体
サンプルとして、「こんにちは」と送られたら「こんにちは!」と返す超シンプルなボットを作れるコードを貼ります。
import os
import json
import requests
import urllib
from base64 import b64encode, b64decode
import hashlib
import hmac
from requests.structures import CaseInsensitiveDict
API_ID = os.environ.get("API_ID") # API ID
SERVER_API_CONSUMER_KEY = os.environ.get("SERVER_API_CONSUMER_KEY") # Server API Consumer Key
BOTNO = os.environ.get("BOTNO") # Bot No
TOKEN = os.environ.get("LW_TOKEN") # 発行したToken
def validate_request(body, signature):
"""
リクエスト検証
"""
# API IDを秘密鍵に利用
secretKey = API_ID.encode()
payload = body.encode()
# HMAC-SHA256 アルゴリズムでエンコード
encoded_body = hmac.new(secretKey, payload, hashlib.sha256).digest()
# BASE64 エンコード
encoded_b64_body = b64encode(encoded_body).decode()
# 比較
return encoded_b64_body == signature
def send_message(content, account_id):
"""
送信
"""
url = 'https://apis.worksmobile.com/' + API_ID + '/message/sendMessage/v2'
headers = {
'Content-Type' : 'application/json;charset=UTF-8',
'consumerKey' : SERVER_API_CONSUMER_KEY,
'Authorization' : "Bearer " + TOKEN
}
params = {
"botNo" : int(BOTNO),
"accountId" : account_id,
"content" : content
}
form_data = json.dumps(params)
r = requests.post(url=url, data=form_data, headers=headers)
if r.status_code == 200:
return True
return False
def handler(event, context):
"""
チャットボット処理
"""
event = CaseInsensitiveDict(event)
headers = event["headers"]
body = event["body"]
# リクエスト検証
if not validate_request(body, headers.get("x-works-signature")):
# 不正なリクエスト
return
# Jsonへパース
request = json.loads(body)
# 送信ユーザー取得
account_id = request["source"]["accountId"]
res_content = {
"type" : "text",
"text" : "テキストのみ対応"
}
# 受信したメッセージの中身を確認
request_type = request["type"]
## Message
if request_type == "message":
content = request["content"]
content_type = content["type"]
## Text
if content_type == "text":
text = content["text"]
if text in "こんにちは":
res_content = {
"type" : "text",
"text" : "こんにちは!"
}
else:
res_content = {
"type" : "text",
"text" : "・・・"
}
# 送信
rst = send_message(res_content, account_id)
res_body = {
"code": 200,
"message": "OK"
}
response = {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": json.dumps(res_body)
}
return response
2. デプロイ
AWS Lambdaへデプロイ (ランタイム: Python 3.7)
トリガーとしてAPI Gatewayを置く。
3. Botの登録
最後に、Botをテナントへ登録する。
- LINE WORKS Developer Consoleで、Botの設定の「Callback URL」に、今回作成したAPI Gatewayのエンドポイントを設定する。
- LINE WORKS 管理画面で、「サービス>Bot」から上記Botを追加する。
最後に
これで、LINE WORKS トークBotをPythonで実装することができました。
LINE WORKSには他にもいろいろAPIがあるので、社内システムとの連携も含め、多彩なチャットボットが実現できると思います。
今の所、SDKがないので自前でURL叩く必要があります。。SDK欲しいですねー
参考
https://qiita.com/comefigo/items/ce573e4ff5d86519eb16
https://qiita.com/tokotan/items/976d35ca56132e0bb5c1
https://utano.jp/entry/2018/01/hmac-sha-256-python/