2022-05-19 discord にファイルをアップロードするアプリケーションの作成
discord にファイルをアップロードするアプリケーションの作成を実施している。
discord はファイルの添付について 8MB という制限があるため、友人が大きなファイルを共有しようとしては、「あ、送信できんかった、容量でかすぎるんか」と言うことが度々発生していた。
ということでアプリケーションを作成することにした。
まあ Google Drive にアップロードしてから共有したり、その他様々な方法で共有はできるはずなので、そこまで必要性のあるアプリケーションではない。単に自分が何か自分が作りたかったというのが一番の理由である。
HTML のフォームから、 S3 にファイルを保存する。その後、 Discord の Webhook にリクエストを送り、チャットに S3 のオブジェクトの URL を投稿する。
- S3 への画像アップロード
- このチュートリアルでハマったこと
- Amazon Cognito
- Discord の Webhook を利用してメッセージを送信
- npm
- webpack
- CDN でのインストールから、 npm でのインストールに
- discord.js を npm でインストールするとエラー
S3 への画像アップロード
Uploading Photos to Amazon S3 from a Browser - AWS SDK for JavaScript
上記のチュートリアルで紹介されている、説明用のアプリケーションを流用。
Amazon Cognito という AWS のサービスを使って、 HTML と JavaScript で構成したブラウザ上のアプリケーションから、直接 S3 にファイルを保存した。
このチュートリアルでハマったこと
S3 の設定において、「Block Public Access」を有効にした状態で Policy を変更しようとした。
すると、この「Block Public Access」の設定によってコンソールからの Policy の設定変更も拒否され、変更ができなかった。
You don't have permissions to edit bucket policy
とか、 s3:PutBucketPolicy
がどうこうとか表示されて IAM を疑ってしまった。
S3 バケットポリシーを変更するときの 403 エラーを解決する
を確認して解決
Amazon Cognito
上記のチュートリアルで Amazon Cognito というサービスを使うことになっていたので、これを学ぶ必要があった。
簡単にこちらのサービスのドキュメントにも目を通した。
Getting started with Amazon Cognito identity pools (federated identities) - Amazon Cognito
- 認証の機能を提供するサービスである。
- user pool と、 identity pool が定義できる
- user pool では、どのような方法でユーザがサインアップ、ログインするかを定義する
- identity pool では、どのユーザに、どのようなアクセス権限 (AWS の各サービスにアクセスする権限) を与えるかを定義する
- 今回の例では、認証なしの unauthorized user を発行し、これにアクセス権限を割り当てる。そのため、 user pool を使う必要はなく、 identity pool を作成するのみでよい。
Discord の Webhook を利用してメッセージを送信
次は discord に Webhook でメッセージを送信するステップ。しかしこれが曲者だった。現在も完了していない。
まず Axios を利用して POST リクエストを送ることにした。しかし、 CORS でアクセスを拒否されてしまった。
素直に CORS に関する正しい手続きを Axios で踏んでもよかったのだけれど、まだ CORS は曖昧な部分があり学習コストがかかる。
discord の Webhook 送信用のライブラリがあるのではないかと探しているとビンゴ、 discord.js というライブラリが存在した。
しかしこのライブラリは、CDN でのインストールが公式でサポートされていなかった。
Installing Node.js and discord.js | discord.js Guide
discord.js を利用するために、アプリケーションに変更を加える必要が生じた。具体的には、ライブラリを CDN 経由で利用する形から、 npm install
で利用する形に変更する必要があった。
npm
まず、 npm について簡単に調べた。
Node.js が JavaScript を動作させるための実行環境で、 npm はパッケージマネージャーである。
次に、 ブラウザ上で動作する、 HTML ベースのアプリケーションでどのように npm のパッケージを利用するのかについて調べた。
Node.jsでモジュールを読み込んでどうやってHTMLで使用するのか?
ブラウザ上で動作させるアプリケーションにおいてこのようなことを行うためには、 Webpack や browserify のような「モジュールハンドラ」を利用し、 ブラウザで扱える形式の JavaScript ファイルを生成する必要があるらしい。
webpack というモジュールハンドラを利用することにした。
webpack
webpackを利用してみる(入門編) | フロントエンドBlog | ミツエーリンクス
webpack.config.js
を生成した。各設定項目の詳細は以下の通り。
- mode : development, production, none が選択できる。production では圧縮されるなど
- entry : スクリプトのエントリーポイント
- output : 出力先のパスと、出力先のファイル名
出力された bundle.js
を HTML で読み込むことで、 npm のライブラリを利用することができた。
しかし、ここでまたひとつ問題が発生した。
<input id="photoupload" type="file" accept="image/*"><br> <button id="addphoto" onclick="addPhoto()">Add Photo</button>
function addPhoto(albumName) { var files = document.getElementById("photoupload").files; ... }
という形で onclick
属性を用いて JavaScript の関数を呼んでいたのだが、 webpack でビルドした形式でスクリプトを読み込んで呼ぶと、 addPhoto is not defined
と表示されてしまう。
package - Uncaught ReferenceError: FUNCTION is not defined within webpack JS bundle - Stack Overflow
window.addPhoto = function addPhoto () {...}
として公開する方法を試したが、結果は変わらなかった。
結局、stackoverflow のこの回答 および stackoverflow-webpack-event-listener/user-container.ts のコードを参考にして、 HTML 自体を JavaScript 側で生成するようにした。
そうすると、この問題は解決した。
CDN でのインストールから、 npm でのインストールに
npm で各種モジュールをインストールできるようになったので、まず aws-sdk を CDN による利用から、 npm install
による利用に切り替えた。
不足したパッケージがあったため、 npm install -S util
で追加インストールを行った。
discord.js を npm でインストールするとエラー
次に discord.js を npm install
した。インストール自体は問題なく済んだのだが、 webpack でビルドをしようとすると凄まじい数のエラーが出た。不足パッケージやその他。
不足パッケージについては手動で指定して追加インストールを行ったのだが、結局エラーは解消されず、また単純なパッケージの不足でないエラーがたくさん出力されたためこの手法は諦めた。
discord.js - Is it possible to make a discord js website and how? - Stack Overflow
で、 discord.js/browser
というものがあると案内されていたが廃止されたようだった。なんせ諸々難しすぎ、めげるようなことが多かった。
改めてライブラリに構わず方法を探し回っていたところ、簡単なスクリプトを見つけた。
js post request example for discord webhooks using the fetch web api
ちょっと実際に小さなスクリプトを書いて動かしてみたところ、そのままで問題なく動作することが確認できた!
ということで、明日以降はこのスクリプトを実際にプロダクトに組み込んでみようと思っている。