Open18

line bot触る

Kumamoto-HamachiKumamoto-Hamachi

イベント(リポジトリにプッシュなど)発生時、指定したURLにPOSTリクエストする仕組みであるWebhookを使っている。下記の3段階を経て応答が行われる。

  1. ユーザーが、LINE公式アカウントにメッセージを送信します。
  2. LINEプラットフォームからボットサーバーのWebhook URLに、Webhookイベントが送信されます。
  3. Webhookイベントに応じて、ボットサーバーからユーザーにLINEプラットフォームを介して応答します。

デモ

https://lineapiusecase.com/ja/api/msgapi.html

Kumamoto-HamachiKumamoto-Hamachi

メッセージを送信する

メッセージオブジェクトは5つまで。
https://developers.line.biz/ja/docs/messaging-api/sending-messages/#methods-of-sending-message

応答メッセージ

応答メッセージは、ユーザーがLINE公式アカウントを友だち追加したり、LINE公式アカウントにメッセージを送ったりしたときに、LINE公式アカウントがユーザーにメッセージで応答する場合に使用します。
=>基本的にbotの運用はこっちのみ考えれば良さそう

任意のタイミングでメッセージを送信する

様々な種類のメッセージ

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

Kumamoto-HamachiKumamoto-Hamachi

ユーザー側の情報収集

コンテンツ(Not テキスト)

ユーザーがLINE公式アカウントに対して送信したコンテンツをWebhookで受信したメッセージIDを使うことで取得できる。
https://developers.line.biz/ja/reference/messaging-api/#get-content

from linebot import LineBotApi

line_bot_api = LineBotApi('<channel access token>')

message_content = line_bot_api.get_message_content('<message_id>')
with open(file_path, 'wb') as fd:
    for chunk in message_content.iter_content():
        fd.write(chunk)

テキスト

ユーザーが送信したテキストは、Webhookのテキストメッセージオブジェクトで受信できます。Webhookを受信した後で、あらためてテキストを取得するためのAPIはありません。

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

プロフィール

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

from linebot import LineBotApi
from linebot.exceptions import LineBotApiError

line_bot_api = LineBotApi('<channel access token>')

try:
    profile = line_bot_api.get_profile('<user_id>')
except LineBotApiError as e:
    # error handle
    ...
Kumamoto-HamachiKumamoto-Hamachi

Messaging APIに関わる用語まとめ

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

開発者とは

LINE Developersコンソールにアクセスする人のこと

プロバイダーとは

LINE Developersサイトでは、サービスを提供し、ユーザーの情報を取得する開発者個人、企業、または団体等をサービス提供者と呼びます。 LINE Developersコンソールでは、サービス提供者をプロバイダーとして登録します。

https://developers.line.biz/ja/docs/line-developers-console/overview/#provider

チャネルとは

チャネルは、Messaging APIやLINEログインといったLINEプラットフォームが提供する機能を、プロバイダーが開発するサービスで利用するための通信路。
チャネルに紐づくアクセストークンなどの情報を利用することで、Messaging APIの各機能を使える。

Kumamoto-HamachiKumamoto-Hamachi

ボット作成に関わる用語

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

チャネルアクセストークンとは

Messaging APIで使用するアクセストークン。3種類あるが任意の期間を設定できるアクセストークンが推奨されている。

任意の有効期間(最大30日)、チャネルシークレットの代わりにJSON Web Token(JWT)

kidとは

アサーション署名キーの公開鍵を登録したことによって発行されたもの。「チャネル基本設定>アサーション署名キー」から取得できます

Webhook URLとは

ボットサーバーのエンドポイントで、Webhookペイロードの送信先

JSON Web Token(JWT)

https://developer.mamezou-tech.com/blogs/2022/12/08/jwt-auth/

HTTPヘッダーやクエリパラメータなどスペースに制約がある環境で使うことを前提に、JSON形式のデータをURLセーフでコンパクトな形式にしたもの。

  • URLセーフする方法
    - JSONデータをBASE64URLエンコードする
  • コンパクトにする
    - よく使われるデータ項目の名称を省略形にする
Kumamoto-HamachiKumamoto-Hamachi

ボット作成 1/2

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

チャネルアクセストークンの発行(チャネルアクセストークンv2.1)

https://developers.line.biz/ja/docs/messaging-api/generate-json-web-token/

アサーション署名キーを発行する

チャネルアクセストークンv2.1を発行する for Python | LINE Developers

    1. アサーション署名キーのキーペアを生成する
    1. 公開鍵を登録し、kidを取得する
$ pip install jwcrypto
from jwcrypto import jwk
import json
key = jwk.JWK.generate(kty='RSA', alg='RS256', use='sig', size=2048)

private_key = key.export_private()
public_key = key.export_public()

print("=== private key ===\n"+json.dumps(json.loads(private_key),indent=2))
print("=== public key ===\n"+json.dumps(json.loads(public_key),indent=2))

チャネル設定からチャネルを選択して、チャネル基本設定タブにアクセスします。次に、アサーション署名キーの横にある[公開鍵を登録する]ボタンをクリック

JWTを生成する

https://developers.line.biz/ja/docs/messaging-api/generate-json-web-token/#jwt-use-python

チャネルアクセストークンv2.1を発行する

「JWTを生成する」の手順で生成したJWTアサーションを指定して、チャネルアクセストークンv2.1を発行
=>チャネルアクセストークンとキーIDをペアで保管

https://developers.line.biz/ja/reference/messaging-api/#issue-channel-access-token-v2-1

Kumamoto-HamachiKumamoto-Hamachi

ボット作成 2/2

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

Webhook URLを設定する

Webhook URL(LINEプラットフォームからボットにイベントを送信する際の送信先URL)をチャンネルの[Messaging API設定]で入力・更新。

Webhookの動作を確認する

Webhookイベントオブジェクトを含むHTTP POSTリクエストが、LINEプラットフォームから先程設定したWebhook URLに送信される。

Kumamoto-HamachiKumamoto-Hamachi

AWS思い出し:Lambda

サーバーレスコンピューティングサービス。(サーバーの設定・管理をしないで計算資源を利用できるサービス、FaaS Function As A Service)、他のAWSサービスと連携させて使うサービス。
😀自動スケーリング、エッジロケーションでの実行(低レイテンシ)、従量課金。
😭データ量の制限、起動に時間かかる

  • めも
    無料枠のリクエスト数(100万)や実行時間(40万GB)割と多いな。
    40万GB秒 = 1GB * 40万秒

イベントソース(Not イベントソースマッピング)

Lambda関数を起動するイベントトリガーとなるもの。
Lambda側にはハンドラーというイベントを検知するためのものが用意されている。
ex)DynamoDBのテーブルに変更があった、S3に変更があった

Lambdaの設定項目

  • IAM Role
  • メモリ容量
  • タイムアウト時間
  • 呼び出しのタイプ(同期・非同期・イベントソース)
    =>synchronous invokes、asynchronous invokes、poll-based invokes

Lambdaのバージョン管理

コードだけでなく設定情報(環境変数など)もバージョンに含まれる
過去のバージョンにはエイリアスで別名を与えられる(prd、test、devなどのタグに出来るってこと)

エイリアスで付けたタグで加重ルーティング(prd2にきたらv1に70%、v2に30%みたいなアクセス振り分けが出来る)

Kumamoto-HamachiKumamoto-Hamachi

Lambdaハンズオンいろいろ

https://aws.amazon.com/jp/getting-started/hands-on/run-serverless-code/

1. はろわ

Lambda は、Amazon CloudWatch Logs にログをアップロードするアクセス権限を持つ、hello-snake-role-qlk1b397 という名前の実行ロールを作成します。

上記ではLambda 関数のコードは編集不可。

関数作成後はテストイベントを作成してみる。

Test Event Name
(unsaved) test event

Response
"value1"

Function Logs
Loading function
START RequestId: a526b1e1-815e-4341-bc1e-9a1d20391c11 Version: $LATEST
value1 = value1
value2 = value2
value3 = value3
END RequestId: a526b1e1-815e-4341-bc1e-9a1d20391c11
REPORT RequestId: a526b1e1-815e-4341-bc1e-9a1d20391c11	Duration: 1.84 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 36 MB	Init Duration: 116.66 ms

Request ID
a526b1e1-815e-4341-bc1e-9a1d20391c11

その他補足

ちなみにCloudWatchに保存されているログは**/aws/lambda/lambda関数名**というLog groupsに保存されている。

Lambda関数を変更したら忘れずDeployボタンを押すこと。

ファイル名_関数名_handlerという名前のハンドラになる。

2. S3と連携させてみる(非同期呼び出し)

S3の標準機能である"イベント通知"を利用してlambdaに通知してやる。
※suffix(拡張子とか)でイベント通知するかのフィルタリングが出来る

(1)バケット作成=>(2)イベント通知設定(ここで通知先のLambda関数も指定する)

その他補足

主に非同期の補足
Event Queue、自動的なリトライ、最大イベント経過時間(未処理のイベントをキューに保存する最大時間)
冪等性の担保(リトライを何度しても同じ結果になること)、DLQ(処理失敗、dead letter queue)がリトライ回数を超えると発行される、並列処理

3. 同期呼び出し(Synchronous Invokes)