前回
LINE WORKSのAPIを使うために必要な各種設定とTokenの発行までを行いました。
前回:https://cloudpack.media/48215
今回は、実際のチャットボットの実装を行います。
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. コード全体
サンプルとして、「こんにちは」と送られたら「こんにちは!」と返す超シンプルなボットを作れるコードを貼ります。
handler.py
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をテナントへ登録する。
1.LINE WORKS Developer Consoleで、Botの設定の「Callback URL」に、今回作成したAPI Gatewayのエンドポイントを設定する。
2.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/