6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[無料][2024年版] LINE Messaging API v3 + Python(Flask) でボットを作る [その0 - v3 での変更点]

Last updated at Posted at 2024-01-04

はじめに

つい最近、LINE の Messenger API の v3 なるものを試す機会があり(この記事)、しばらくいじっているうちにやっと使い方がわかってきたのでここにメモしておこうと思います。

わざわざこうやって記事にまとめようと思った理由は、もちろん自分用の備忘録が一番ですが、他にも

  • Line は日本、タイ、台湾などでしか使われていないガラパゴスツールなので、Stack Overflow に情報がない
  • Qiita の情報も、v3 以前のものが多い
  • そもそもPython で開発している人も多くない
  • 本家 line-bot-sdkGitHub の説明が少なすぎる

などの理由から、せっかくなので共有しておこうと思ったからです。あくまで個人開発のレベルで、専門的なことはパッパラパーなのですが、こんな素人の私の記事でも多少は役に立つ内容にしようと思います。

ちなみにどうしても Python + Flask を使いたい方向けの解説です。最近はGAS(Google Apps Script)を使って開発する方も多く、そちらの方がGCPでデプロイもできるので楽です。私が Python を使う理由は機械学習や自然言語処理系のライブラリを使っているからであり、そういったものを必要としないならばGASの方が簡単にできると思います、記事もたくさん見つかります。

これから何回かに分けて記事を書いていく予定ですが、今回はまず v3 という新しいバージョンがどういうものか、実際に使ってみた内容をまとめてみます。既に Flask + Messeging API を使って開発したことがある方向けの説明なので、「これから Python を使ってボット開発を始めたい!」という方は読み飛ばして、次回以降の記事から読んでいただいても構いません。

v3 について

2023年6月頃に導入された OpenAPI 仕様に沿った新バージョンのSDK(ソフトウェア開発キット)の仕様になります。ただし、APIのエンドポイントは https://api.line.me/v2/bot/ のままで、リクエストの方法も同じです。

こちらにも書かれているように将来的には v3 に統一化するようで、現状でも deprecated warning が出てくるので精神衛生上よろしくありません。なのでこれから開発をする方は、v3 で始めた方が良いかと思います。

v3 での変更点

使っていて気づいた変更点をまとめると、

  1. 認証用のクラスをインスタンス化
  2. クラスの再編成
  3. 返信時は、メッセージタイプに関わらず ReplyMessageRequest オブジェクトとして渡す
  4. キーワードのキャメルケース対応化
  5. Flex Message 用のクラスが導入

というものです。

1. 認証用のクラスをインスタンス化

line-bot-sdk でメッセージを送信する際は、今まで

app = Flask(__name__)

## APIインスタンス化
line_bot_api = LineBotApi(CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(CHANNEL_SECRET)

## callback認証
@app.route("/callback", methods=['POST'])
def callback():
    signature = request.headers['X-Line-Signature']
    body = request.get_data(as_text=True)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return 'OK'

## テキストメッセージ返信
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    
    ### ここでメッセージ処理する

    ## 返信
    line_bot_api.reply_message(event.reply_token, message)

のような形式だったかと思います。これが v3 においては、大幅に変更されています(こちらを参照)。以下は公式のオウム返しサンプルコードです。

app = Flask(__name__)

configuration = Configuration(access_token='YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')


@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        app.logger.info("Invalid signature. Please check your channel access token/channel secret.")
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessageContent)
def handle_message(event):
    with ApiClient(configuration) as api_client:
        line_bot_api = MessagingApi(api_client)
        line_bot_api.reply_message_with_http_info(
            ReplyMessageRequest(
                reply_token=event.reply_token,
                messages=[TextMessage(text=event.message.text)]
            )
        )

発行した CHANNEL_ACCESS_TOKEN を渡すのはAPIオブジェクトではなく、Configurtion という認証用のオブジェクトに代わっています。line_bot_api のインスタンス化は関数内部(イベントハンドラー内)で行われるようになり、名称も LineBotApi から MessagingApi に変更されています。

ちなみに、このAPIのインスタンス化は関数内部ではなく最初にやってしまっても動くことは動きます。つまり、

app = Flask(__name__)

configuration = Configuration(access_token=CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(CHANNEL_SECRET)

## APIインスタンス化
with ApiClient(configuration) as api_client:
	line_bot_api = MessagingApi(api_client)

@app.route("/callback", methods=['POST'])
def callback():
    ...

@handler.add(MessageEvent, message=TextMessageContent)
def handle_message(event):
    
    ## メッセージ処理諸々
    
    line_bot_api.reply_message(
		ReplyMessageRequest(
			replyToken=event.reply_token,
			messages=message
		)
	)

のようにするということです。ただし、認証に関するタイムアウト的な問題なのか、時間が空くとプロトコルエラーが起きたり起きなかったりします(ネットワーク関連の知識が全然なくて申し訳ありません)。なので、素直に関数内でその都度インスタンス化することをオススメします。

また、返信用のメソッドも v3 以前では line_bot_api.reply_message() だったのが、v3 では line_bot_api.reply_message_with_http_info() という長ったらしいものに変わっています。

ですが、実は v3 にも .reply_message() が残されており、ソースコードを見る限りこの内部で .reply_message_with_http_info() を呼び出している(違いはあるようですが私にはわかりません)ので、私は短い方を使っています。上記のコードもそう修正しています。

2. クラスの再編成

v3 以前で linebot.models にあった様々なクラスは、送信処理関連の linebot.v3.messaging と webhook 受信処理の linebot.v3.webhooks に分離しています。具体的には

linebot.v3.messaging

必ず使うもの

  • Configuration : 認証用クラス
  • MessagingApi, ApiClient : APIのインスタンス化

メッセージ送信方法別 (APIドキュメント)

  • ReplyMessageRequest : webhook に応答して返信する時
  • PushMessageRequest : 任意のタイミングでプッシュメッセージを送信する時

メッセージタイプ別 (APIドキュメント)

  • TextMessage, AudioMessage, TemplateMessage, FlexMessage など

アクションタイプ別 (APIドキュメント)

  • PostbackAction, MessageAction, URIAction など

リッチメニュー関連

linebot.v3.webhooks

イベントタイプ別 (APIドキュメント)

  • FollowEvent, MessageEvent, PostbackEvent など

コンテンツ別 (APIドキュメント)

  • TextMessageContent, PostbackContent, AudioMessageContent など

のようになっています。従来 webhook のコンテンツ用だった TextMessage は、v3 では TextMessageContent となり、逆に TextMessage はテキストをメッセージオブジェクト化するためのクラスとなっています。

3. 返信時は、メッセージタイプに関わらず ReplyMessageRequest オブジェクトとして渡す

上述の v3 のサンプルコードの返信部分を確認してみましょう。

@handler.add(MessageEvent, message=TextMessageContent)
def handle_message(event):
    with ApiClient(configuration) as api_client:
        line_bot_api = MessagingApi(api_client)
        line_bot_api.reply_message_with_http_info(
            ReplyMessageRequest(
                reply_token=event.reply_token,
                messages=[TextMessage(text=event.message.text)]
            )
        )

line_bot_api.reply_message_with_http_info() の中身が、ReplyMessageRequest というクラスになっており、messages というキーワードで各種のタイプのメッセージオブジェクトのリストを受け取るようになっています。

以前は .replay_message() メソッドに直接 TextSendMessageAudioSendMessage などのクラスを渡していました。v3 ではそれらを一旦 Request オブジェクトにしてから、.replay_message() に渡すという形式になっています。reply_token も、この ReplyMessageRequest に渡します。

4. キーワードのキャメルケース対応化

サンプルコードでは全て以前同様にスネークケースで書かれているのですが、エディタ内ではキャメルケースで表示されたので気づきました。これはエイリアスされていて、どちらで書いても動きます。例えば上述の ReplyMessageRequest なら、

ReplyMessageRequest(
    reply_token=event.reply_token,
    messages=[TextMessage(text=event.message.text)]
)

ReplyMessageRequest(
    replyToken=event.reply_token,
    messages=[TextMessage(text=event.message.text)]
)

の両方が可能です。旧コードをコピーして v3 用に修正する時にはスネークケースのままで問題ありません。

5. Flex Message 用のクラスが導入

これは前回の記事で紹介したんですが、FLex Message を使うためのクラスが充実しています。JSONや辞書を一切書くことなく、オブジェクトの組み合わせで全てが完了します。

もちろん Flex Message Simulator を使ってのプレビュー確認は欠かせませんのでJSON書き出しは使います。また、コーディング量自体にそこまで大差はないですが、各クラスをインスタンス化した際に適切なパラメータを与えないと ValidationError が出て怒られるので、非常にデバッグがしやすくなりました。


これ以外にも細かな変更点はたくさんあると思いますが、使いながらまた追記していきます。

ということで、次回の記事からタイトルの [無料][2024年版] のボット開発の内容に入っていきます。

目次 : [無料][2024年版] LINE Messaging API v3 + Python(Flask) でボットを作る

GitHub レポジトリ
older_version 内に、各回時点での app.pyrequirements.txt があります。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?