Line Messaging API を使う

# はじめに
こんにちは。初投稿となります！
普段、Qiita にはお世話になっているので、自分も何かしらのアウトプットで誰かの助けになれればと思い、投稿してみることにしました。
また、自分の忘備録の意味合いもあります。
つたない文章ではありますが、ぜひ最後まで読んでいただけると嬉しいです！

初テーマについては、[Line Messaging API](https://developers.line.biz/ja/services/messaging-api/) にしました。
Line で bot を作れるあれです。
自分が何かを開発するときに、UI の作成がいつもネックになるので、UI の代わりとして重宝しています。
簡単な入力に対する応答とかであれば、Web アプリみたいなインターフェイスを作らなくても、Line bot で対応できます。
今回は、Messaging API を使用して、bot から簡単な応答ができるまでをみていきます。
では、早速やっていきましょう！

# Messaging API の仕組み
Messaging API では自分で用意したボットサーバーと LINE プラットフォームの間でデータを交換する仕組みになっています。
Line 上で bot にメッセージを送ると、そのメッセージが LINE プラットフォームからボットサーバーに送信されて、ボットサーバーで処理された結果が Line 上で bot によって返信されるといったイメージです。

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115963/c1a7d02a-2abb-5a99-9a11-974d6a16740a.png)
引用元：https://developers.line.biz/ja/docs/messaging-api/overview/#how-messaging-api-works

今回は、ボットサーバーとして [AWS Lambda](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html) を使用します。
コードをデプロイするだけで必要な場合にのみ実行でき、自動的にスケーリングし、コードの実行した時間に基づいた課金となるので、経済的かつめちゃくちゃ便利です。

# 実装
手順は以下のようになります。
1. LINE Developers に登録
2. プロバイダーとチャネルの作成　
3. AWS Lambda の実装
4. bot のテスト

## 1. LINE Developers に登録
Messaging API を使うためには [LINE Developers](https://developers.line.biz/ja/) への登録が必要になります。
登録しておきましょう。

## 2. プロバイダーとチャネルの作成
登録／ログイン後に、LINE Developers コンソールでプロバイダーとチャネルを作成します。
プロバイダーとチャネルとは何ぞやと思った方は[こちら](https://developers.line.biz/ja/docs/line-developers-console/overview/)を参照ください。
プロバイダーがサービス提供者の単位、チャネルが提供するサービスの単位みたいなイメージです。

### 2-1. プロバイダーの作成
コンソール画面の左側の Providers を選択後、Create から作成できます。
任意の名前で作成しましょう。

### 2-2. チャネルの作成
作成したプロバイダーの画面で、チャネルを新規作成します。
チャネルのタイプの選択画面が開くので、Messaging API を選択します。
色々と入力が求められるので、よしなに入力して作成を完了させます。

作成されたチャネルの設定をします。
Messaging API タブを選択し、下部の Channel access token を発行してメモしておきます。
また、Basic settings タブの Channel secret もメモしておきます。
これらは、後ほど実装する AWS Lambda から LINE Messaging API にアクセスする際に必要な情報となります。

次に bot の応答設定を編集しておきます。
Messaging API タブの Auto-reply messages の edit ボタンを押します。
![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115963/2c2eb0c4-bccb-a3a2-c2d2-ca9fadfabbb0.png)

別ページに遷移するので、Webhook は有効に、応答メッセージは無効にしておきます。その他の設定は任意に設定してください。
![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115963/80cc20db-a48b-3ffc-7d7d-9622ed7868cb.png)


## 3. AWS Lambda の実装
ボットサーバーとなる AWS Lambda の実装を行っていきます。
AWS Lambda は[関数 URL](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-urls.html)を使用すれば単体でも公開できるのですが、今回は前段に [API Gateway](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/welcome.html)を置く構成にします。

### 3-1. Lambda 関数の作成
新規に Lambda 関数を作成してください。
今回は開発言語として Python を使用するので、ランタイムは Python で作成します。
※現状の最新である Python 3.11 だとライブラリの依存関係でエラーが発生するようです。Python 3.10 だとこの後の手順で実装して動作することを確認しています。

### 3-2. Lambda レイヤーの作成
Messaging API では、[各種言語に対応する SDK](https://developers.line.biz/ja/docs/messaging-api/line-bot-sdk/) が公開されています。
今回は、Python の SDK である [LINE Messaging API SDK for Python](https://github.com/line/line-bot-sdk-python) を使用します。

Lambda 関数では基本的なライブラリのみが導入されており、デフォルトでは LINE Messaging API SDK for Python はインストールされていません。
そこで、Lambda 関数でこのライブラリを使用できるように、[Lambda レイヤー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/chapter-layers.html)を作成します。
デプロイパッケージにライブラリを含めることもできるのですが、複数の bot を作成する場合などに毎回ライブラリを入れるのも面倒なため、レイヤーを作成して再利用しやすくしておきます。

まずは[ライブラリをパッケージング](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/packaging-layers.html)します。
Python と pip が導入された環境で、以下のようなコマンドで SDK をダウンロードします。
```
$ mkdir python
$ cd python
$ pip install line-bot-sdk -t .
```
作成された Python フォルダを zip で圧縮します。

次に[レイヤーを作成](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/creating-deleting-layers.html#layers-create)します。
AWS マネジメントコンソールの レイヤー > レイヤーの作成 から先ほどの zip ファイルをアップロードしてレイヤーを作成します。

最後に Lambda 関数に[レイヤーを追加](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/adding-layers.html)します。
3-1 で作成した Lambda 関数のページの下部から作成したレイヤーを追加します。
これで、Lambda 関数から SDK がインポートできるようになりました。

### 3-3. コードの実装
コードの実装を行います。今回は送信したメッセージと同じメッセージをオウム返ししてくれる bot を作成します。
下記のコードでは SDK の[サンプル](https://github.com/line/line-bot-sdk-python#synopsis)を参考にしつつ、Lambda 関数向けに変更しています。
アクセストークンについては、Lambda の[環境変数](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html)に格納しています。

下記のコードを Lambda 関数にデプロイします。
```
import os
import logging
from linebot.v3 import (
    WebhookHandler
)
from linebot.v3.exceptions import (
    InvalidSignatureError
)
from linebot.v3.messaging import (
    Configuration,
    ApiClient,
    MessagingApi,
    ReplyMessageRequest,
    TextMessage
)
from linebot.v3.webhooks import (
    MessageEvent,
    TextMessageContent
)

logger = logging.getLogger()
logger.setLevel(logging.ERROR)

channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN')
channel_secret = os.getenv('LINE_CHANNEL_SECRET')

configuration = Configuration(access_token=channel_access_token)
api_client = ApiClient(configuration) 
line_bot_api = MessagingApi(api_client)
handler = WebhookHandler(channel_secret)

def lambda_handler(event, context):

    signature = event["headers"]["x-line-signature"]
    body = event["body"]
    
    @handler.add(MessageEvent, message=TextMessageContent)
    def handle_message(event):
        line_bot_api.reply_message_with_http_info(
            ReplyMessageRequest(
                reply_token=event.reply_token,
                messages=[TextMessage(text=event.message.text)]
            )
        )

    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        message = "Invalid signature. Please check your channel access token/channel secret."
        logger.error(message)
        return {'statusCode': 400,'body': message}
    
    return {'statusCode': 200, 'body': "OK"}
```

### 3-4. API の公開
API Gateway で Lambda 関数を API として公開します。
以下の手順で API を作成します。詳細な手順は[この辺り](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-create-api.html)を参照してください。
1. 新規 API を REST API として作成する。
2. メソッドを POST で作成する。統合タイプは Lambda 関数を選択し、作成した Lambda 関数を指定する。「Lambda プロキシ統合の使用」にチェックを入れる。
3. API のデプロイを行う。表示される API の URL はメモしておく。
4. Messaging API のコンソールに移動し、Webhook URL に 3 の URL を設定し、Use webhook にチェックを入れる。その他の項目は任意でチェックを入れる。
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3115963/2f772642-d951-3004-3357-a19b7a6e95fc.png)


## 4. bot をテストする
作成した bot のテストを行います。
Messaging API のコンソールに bot の QR コードがあるので、読み込んで LINE で友達追加します。
bot にメッセージを送ると、送信されたメッセージと同じものが返ってきます。メッセージ時が返ってくれば成功です。
もしメッセージが返ってこない場合は、Lambda 関数でエラーが発生しているなどの原因が考えられます。Lambda 関数のログは CloudWatch Logs に出力されているので、必要に応じてデバッグに活用してください。

# おわりに
今回は Line Messaging API を使って、Line bot を作成しました。
Lambda 関数で任意の処理を実装すれば、簡単にいろいろなことができる bot が作成できます。
自分は Lambda 関数から生成 AI を呼び出して質問に答えてくれたり画像を生成してくれる bot や [VOICEVOX](https://voicevox.hiroshiba.jp/) を使って送信したメッセージを音声化して返してくれる bot など、様々な機能を持った bot を作成して遊んでいます。
UI 部分を LINE に完全に任せられるのは非常に便利です。
よかったら LINE で bot を作成してみてください。