LINEボットで投稿した画像をAWS S3に保存する

多くの人が、同じことをブログに書かれてますが、自分用の備忘録として残します。

コードはほとんどChatGPT、
AWSの設定はこちらの方のブログを見ながらやりました。
https://cloud5.jp/lambda-linebot-s3/
ありがとうございました。


<br>

## 準備

LINE Messaging API の設定
こちらの 「2-2．LINEチャットボット開発前の設定」をご覧ください。

https://qiita.com/tatsuya1970/items/3e41dbeddc0e2d2fb881#2-2line%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%83%9C%E3%83%83%E3%83%88%E9%96%8B%E7%99%BA%E5%89%8D%E3%81%AE%E8%A8%AD%E5%AE%9A

<br>

作業ディレクトリを作成
```
mkdir line-s3
cd line-s3
```

必要なライブラリをインストールする
```
pip install line-bot-sdk 
pip install bot3
pip install requests
```

私は「pip install bot3」で
こんなエラーがでた、
```
ERROR: Could not find a version that satisfies the requirement bot3 (from versions: none)
ERROR: No matching distribution found for bot3
```

これだと通った。
```
pip3 install boto3 --upgrade
```

<BR>

## コード作成

 「lambda_function.py」を作成する
※このファイル名以外だと読み込まれないので注意

```lambda_function.py
import json
import os
import urllib.request
import logging
import boto3

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

LINE_CHANNEL_ACCESS_TOKEN = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
S3_BUCKET_NAME = os.environ['S3_BUCKET_NAME']  # S3バケット名を環境変数から取得

REQUEST_URL = 'https://api.line.me/v2/bot/message/reply'
DOWNLOAD_URL = 'https://api-data.line.me/v2/bot/message/{messageId}/content'
REQUEST_METHOD = 'POST'
REQUEST_HEADERS = {
    'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN,
    'Content-Type': 'application/json'
}

s3_client = boto3.client('s3')  # S3クライアントの初期化

def lambda_handler(event, context):
    logger.info(event)
    body = json.loads(event['body'])
    events = body['events']
    if events[0]['message']['type'] == 'image':
        message_id = events[0]['message']['id']
        reply_token = events[0]['replyToken']
        save_image_to_s3(message_id)
        reply_to_line(reply_token, '画像を保存しました！')
            
    return 0

def save_image_to_s3(message_id):
    download_url = DOWNLOAD_URL.format(messageId=message_id)
    download_headers = {'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN}

    # LINEから画像をダウンロード
    request = urllib.request.Request(download_url, headers=download_headers)
    response = urllib.request.urlopen(request)
    image_data = response.read()

    # S3に画像をアップロード
    file_path = 'line_images/' + message_id + '.jpg'
    s3_client.put_object(Bucket=S3_BUCKET_NAME, Key=file_path, Body=image_data)

def reply_to_line(reply_token, message_text):
    reply_message = [
        {
            'type': 'text',
            'text': message_text
        }
    ]
    params = {
        'replyToken': reply_token,
        'messages': reply_message
    }
    request = urllib.request.Request(
        REQUEST_URL, 
        json.dumps(params).encode('utf-8'), 
        method=REQUEST_METHOD, 
        headers=REQUEST_HEADERS
    )
    urllib.request.urlopen(request, timeout=10)
```

これをzipファイルにする。
<br>

## AWS

### S3

S3の設定はこちらをご覧ください。

https://qiita.com/tatsuya1970/items/1d1ad8fe4c67b88282c6

<br>

### Lambda 

新しい関数を作成し、
さきほど作成したzipファイルをアップロードする。

Pythonhのバージョンは「lambda_function.py」と同じにする。

アップロードされた。
[![Image from Gyazo](https://i.gyazo.com/817c9b25efc9359c2dde0d5021c2f6fd.png)](https://gyazo.com/817c9b25efc9359c2dde0d5021c2f6fd)

<br>

#### 環境変数

[![Image from Gyazo](https://i.gyazo.com/d1907e0bbd266911e00429803e76683f.png)](https://gyazo.com/d1907e0bbd266911e00429803e76683f)

[![Image from Gyazo](https://i.gyazo.com/5f37532b84ad36833739ccabadea8105.png)](https://gyazo.com/5f37532b84ad36833739ccabadea8105)

#### トリガー設定
Lambda画面からトリガーを追加を押下する

[![Image from Gyazo](https://i.gyazo.com/c181f3e243c1b0cb4afc4fcaed5bb413.png)](https://gyazo.com/c181f3e243c1b0cb4afc4fcaed5bb413)


トリガーの設定で「API Gateway」を選択する
APIタイプはHTTP APIで、セキュリティはオープンを選択する
[![Image from Gyazo](https://i.gyazo.com/b894ab489537142a12724d437f0f4de6.png)](https://gyazo.com/b894ab489537142a12724d437f0f4de6)




### API Gateway

アクション　＞　メソッドの作成
[![Image from Gyazo](https://i.gyazo.com/6246bf5d51e5bad63342a6167ae45643.png)](https://gyazo.com/6246bf5d51e5bad63342a6167ae45643)


「POST」を選択
[![Image from Gyazo](https://i.gyazo.com/5303c37e2c32c0acf1e33c91c3796f57.png)](https://gyazo.com/5303c37e2c32c0acf1e33c91c3796f57)

以下のように設定
[![Image from Gyazo](https://i.gyazo.com/91b8ab90bb61ed37afdd20fe77cf368a.png)](https://gyazo.com/91b8ab90bb61ed37afdd20fe77cf368a)

ANYを削除
[![Image from Gyazo](https://i.gyazo.com/9e8ed4a0fa7ff20f4703e20f74585358.png)](https://gyazo.com/9e8ed4a0fa7ff20f4703e20f74585358)


デプロイ
[![Image from Gyazo](https://i.gyazo.com/5af8268b7f8256a437fdec34e96392e9.png)](https://gyazo.com/5af8268b7f8256a437fdec34e96392e9)

<br>
デプロイされるステージは「default」を選択

<br><br>



さっき作ったAPI Gateway を削除
[![Image from Gyazo](https://i.gyazo.com/1cba6b8029d44d2e129be0b0634b24a4.png)](https://gyazo.com/1cba6b8029d44d2e129be0b0634b24a4)

<br>

## アクセス権限の設定

ここは毎回忘れるので、自分用に作って良かった。

アクセス権限　
ロール名をクリック
[![Image from Gyazo](https://i.gyazo.com/889dce3fbbb9f326fd7a5d05e5a17890.png)](https://gyazo.com/889dce3fbbb9f326fd7a5d05e5a17890)

許可を追加　＞　ポリシーをアタッチ
[![Image from Gyazo](https://i.gyazo.com/0ba73a9eefc05998432c77fb66e4668f.png)](https://gyazo.com/0ba73a9eefc05998432c77fb66e4668f)

[AmazonAPIGatewayInvokeFullAccess]を追加

[![Image from Gyazo](https://i.gyazo.com/ba04c00a6c92d82903bb0abb28e3c134.png)](https://gyazo.com/ba04c00a6c92d82903bb0abb28e3c134)


もう１つ「AmazonS3FullAccess」を追加
[![Image from Gyazo](https://i.gyazo.com/1e81da57d14e1e2f626dd194ea387a67.png)](https://gyazo.com/1e81da57d14e1e2f626dd194ea387a67)

エンドポイントURLを LINE Developer のwebhookに登録する
[![Image from Gyazo](https://i.gyazo.com/5d0fb1101249e23a570596f7989d3e6f.png)](https://gyazo.com/5d0fb1101249e23a570596f7989d3e6f)


これで、LINEボットに画像を投稿すると、AWS S3に保存されます。

<br>