WebSocketでLINEに送った画像を複数ブラウザに共有する

構成

LineBotに画像を送信すると、WebSocket接続しているクライアントのブラウザの画像がリロードせずに切り替わるというものです。

https://drive.google.com/file/d/1Jy9BZB0Dy-7wDY6M_3gtuX0C8h_fIaUR/view

フォルダ構成

今回はサイトをホスティングするS3以外はSAMを使用して作成します。

.
├── src
│   ├── onconnect
│   │   └── lambda_function.py
│   ├── ondisconnect
│   │   └── lambda_function.py
│   ├── sendimage
│   │   └── lambda_function.py
│   └── sentfromline
│       └── lambda_function.py
├── template.yaml
└── samconfig.yaml

github.com

LINEBotの作成

LINEBotを作成し、アクセストークンを発行してください。
発行したアクセストークンはsamconfig.yamlのLINECHANNELACCESSTOKENに記入してください。

Requestsレイヤーの作成

LINEからメッセージ情報をWebhook経由で受け取った際、Lambdaでメッセージ情報を元に画像を取得するためrequestsモジュールを使用します。
現在のLambda Python3.11ではサポートされていないので、作成したLayerをImportして使用しています。
作成したLayerのARNもsamconfig.yamlのRequestsLayerArnに記入してください。
(Layerの作成方法については省略します)

サービスの作成

templateファイルだけ指定すれば、設定等はsamconfig.yamlを参照してくれます。

sam deploy --template ./template.yaml

ホスティング用のS3の作成

LINEから送信した画像を保存するS3バケットと同様にPublicなS3をもう1つ作成し、シェルスクリプトでindex.htmlをアップロードすることは可能だと思いますが
index.htmlに記載しているWebSocketのURLを記入する必要があるので、今回は手動で作成しています。
・アクセス許可はブロックパブリックアクセスを全て無効
バケットポリシーはフルアクセス
・静的Webサイトホスティングを有効化
しています。
※レポジトリにあるindex.htmlをアップロードしておいてください

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::{your-bucket-name}/*"
        }
    ]
}

LINEのMessageing API設定でWebhookURLを設定する

作成された「photo-share」API GatewayのURLをWebhook URLに設定します。

https://--------.execute-api.{your-region}.amazonaws.com/saveImageFromLine

index.htmlのWebSocket URLを記入する

作成された「wsApiTest」API GatewayのURLを記入します。

const socket = new WebSocket("wss://----.execute-api.{your-region}.amazonaws.com/{your-stage}");

動作確認

S3のページをブラウザで開き「WebSocket接続中」と表示されている状態でLINEBotに画像を送信すると、画像が反映されます。

参考記事

ChatGPTで簡単! 余興に使えるAWSサーバーレスアプリ開発入門 - Speaker Deck

AWSでWebSocketを使って画像共有 - NIFTY engineering