firebaseを使って簡単なチャットシステムを作ってみた（windows os向け）

# 初めに
皆さんこんにちは。今回はfirebaseを使って簡単なチャットシステムを作っていきます。
# 今回使う外部API
今回はfirebase(Google)を使います。
# ファイル構成
今回のファイル構成は以下の通りです(今回は利用規約を省いています。)
```
chatj
   |--css
   |    |
   |    |--style.css
   |
   |--html
   |      |
   |      |--main.html
   |      |
   |      |--riyou.html(利用規約(多分なくてもok))
```
# 必要なもの
今回必要なものは以下の通りです。
・Googleアカウント(firebaseのログイン用)
まだアカウントを持ってないよという方は、下のurlからGoogleアカウントを作成してください。（電話番号は必要ありません。（多分））
https://qiita.com/qqn5192/items/24edee88d572b8ba35cf
・node.js 18.0以降(firebase CLIに必要(バージョンはfirebaseで確認してください。))サイト↓
https://nodejs.org/en/download/package-manager
# firebaseのプロジェクトを作る
1,firebase.comにアクセスします。url↓
https://console.firebase.google.com/
2,Googleアカウントにログインします。（ログインしている人はスキップしてください。）
3,プロジェクトを既に作ったことがあるという人はプロジェクトを追加、まだプロジェクトを一度も作成していないという方はプロジェクトを作成をクリックしてください。
4,画面の指示に従います。
5,プロジェクトを作成したら、左上側にある歯車アイコンをクリックして、「プロジェクトの設定」をクリックします。
6,全般をクリックして、下にスクロールします、すると<／>のようなボタンがあるので、それをクリックします
7,アプリ名を指定します。(入力したら、アプリを登録をクリック)

8,firebase SDKの追加にきたら、scriptタグを使用するをクリックます。（firebaseconfig内のデータはあとで使用するので、メモ帳などにコピペしておいてください。）
cmdを管理者で起動して、下のコマンドを入力します(すでにインストールしている方はスキップしてください。)
まず、したのコマンドを入力して、firebaseがインストールされているかを確認してください。
```:cmd
firebase --version
```
上のコマンドを入力してfirebaseのバージョン情報が出てきたら、すでにfirebase cliをインストールしているので、スキップしてください。
バージョンが出てこなかったという方は、下の２つのコマンドを実行してください（多分管理者権限が必要）
```:cmd
npm install -g firebase-tools
```
```:cmd
npm install firebase
```
※...npmはnode.jsが入っていないと使用できません。
インストールできたら、次の順番で（上から）cmdでコマンドを実行してください
```:cmd
firebase login
```
firebaseにGoogleアカウントでログインします。（エラーがでても大丈夫です）
```:cmd
firebase init
```
プロジェクトを開始（？）します。（cmdの指示に従ってください）
```:cmd
firebase deploy
```
プロジェクトをデプロイします。
これで、プロジェクトの準備は完了しました。
## チャット-管理者版※
※...プログラムの都合上、どうやってもほかのユーザーがほかのユーザーの投稿したものを削除できてしまうので、管理者版と一般版に分けさせていただきました。
### コピペする(css)
style.cssに以下のコードをコピペしてください。
```css:style.css
header {

    background-color: rgb(66, 66, 66);
    color: white;
    text-align: center;
    height: 70px;
    padding: 20px 0;
    width: 100%;

}
footer {

    background-color: rgb(66, 66, 66);
    color: white;
    height: 150px;
    padding: 10px 0;
    width: 100%;

}
a {

    color:rgb(95, 106, 250);

}
a:hover {

    color: rgb(6, 169, 209);

}
.text-2 {
    width: 400px;
    height: 100px !important;
    resize: vertical; /* 垂直方向にのみリサイズ可能にする */
}

.btn {

    width: 100px;
    height: 30px;
    background-color: rgb(87, 82, 82);
    color: white;
    border: none;
    margin-top: 20px;

}
.btn:hover {

    background-color: rgb(172, 172, 172);

}
li {

text-align: center;

}
.container {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    height: auto;
    overflow-y: auto;
    word-wrap: break-word; /* コンテンツが端にきたら折り返す */
}


#res {
    max-width: 600px;
    margin-top: 20px;
}

#res > div {
    border: 1px solid #ccc;
    padding: 10px;
    margin-bottom: 10px;
}
body {

    overflow: scroll;

}
```
## コピペする（管理者版）
次に、下のコードをコピペしてください
```html:main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>掲示板(管理者版)</title>
    <link rel="stylesheet" href="../css/styleAdmin.css">
</head>
<body>
    <header>
        <center>
        <h1>掲示板(管理者版)</h1>
        </center>
    </header>
    <div class="container">
        <h2>掲示板</h2>
        <p>現在管理者モードとして動作しています。(できるだけ通常版を使用するように)</p>
        <p>相手の気持ちを考えて投稿しましょう。</p>
        <h2>投稿する</h2>
        <p>ユーザー名を入力(ない場合は空白でok※管理者の名前使用可)</p>
        <input type="text" id="username" class="text" placeholder="ユーザー名を入力">
        <p>投稿する内容(必須)</p>
        <textarea class="text-2" id="text"></textarea>
        <br>
        <input type="button" class="btn" onclick="conf()" value="投稿する">
        <div id="res"></div>
    </div>
    <footer>
        <center>
           
            <p>© 2024 created by "your_name"</p>
        </center>
    </footer>
    <script src="https://www.gstatic.com/firebasejs/9.1.2/firebase-app-compat.js"></script>
    <script src="https://www.gstatic.com/firebasejs/9.1.2/firebase-database-compat.js"></script>
    <script src="https://www.gstatic.com/firebasejs/9.1.2/firebase-auth-compat.js"></script>
    <script>
        
        const firebaseConfig = {
            apiKey:"YOUR_APIKEY",
            authDomain: "YOUR_AUTHDOMAIN",
            databaseURL: "YOUR_DATABASEURL",
            projectId: "YOUR_PROJECTID",
            storageBucket: "YOUR_STRAGEBUCKET",
            messagingSenderId: "YOUR_MESSAGINGSENDERID",
            appId: "YOUR_APPID",
            measurementId: "YOUR_MEASUREMENTID"
        };
        const firebaseApp = firebase.initializeApp(firebaseConfig);
        const database = firebaseApp.database();
        function conf() {
            let confi = confirm("本サービスでは、プログラムの都合上、一度投稿した内容は絶対に誰かに観覧されます（多分）それでも投稿しますか？");
            if (confi) {
                sendMessage();
            } else {
                return;
            }
        }
        function sendMessage() {
            const username = document.getElementById("username").value || "anonymous";
            const message = document.getElementById("text").value.trim();
            if (message !== '') {
                database.ref('messages').push({
                    username: username,
                    text: message,
                    userId: firebase.auth().currentUser ? firebase.auth().currentUser.uid : null,
                    timestamp: firebase.database.ServerValue.TIMESTAMP
                });
                document.getElementById("text").value = '';
            }
        }
        database.ref('messages').orderByChild('timestamp').on('child_added', snapshot => {
            const message = snapshot.val();
            const chatBox = document.getElementById('res');
            const messageElement = document.createElement('div');
            messageElement.innerText = `${message.username}: ${message.text}`;
            if (message.userId === firebase.auth().currentUser?.uid) {
                const deleteButton = document.createElement('button');
                deleteButton.textContent = '削除';
                deleteButton.addEventListener('click', () => deleteMessage(snapshot.key));
                messageElement.appendChild(deleteButton);
            }
            chatBox.prepend(messageElement);
        });
        function deleteMessage(messageKey) {
            if(prompt("これがロボットによる操作ではないことを確認します。'delete'と入力してください。") === "delete"){
                database.ref('messages').child(messageKey).remove()
                    .then(() => {
                        console.log('メッセージが正常に削除されました。');
                    })
                    .catch(error => {
                        console.error('メッセージの削除エラー:', error);
                    });
            }
        }
    </script>
</body>
</html>
```
※...databaseURLはまだどうやって取得したのかが不明なので（修正時にgptが出したので）またわかったら説明します。すみません。
## コピペ(一般)
一般のものに、以下のものをコピペしてください。
```html:main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>掲示板</title>
    <link rel="stylesheet" href="../css/style.css">
</head>
<body>
    <header>
        <h1>掲示板</h1>
    </header>
    <div class="container">
        <h2>掲示板</h2>
        <p>相手の気持ちを考えて投稿しましょう。</p>
        <h2>投稿する</h2>
        <p>ユーザー名を入力(ない場合は空白でok)</p>
        <input type="text" id="username" class="text" placeholder="ユーザー名を入力">
        <p>投稿する内容（必須）</p>
        <textarea class="text-2" id="text"></textarea>
        <br>
        <input type="button" class="btn" onclick="conf()" value="投稿する">
        <div id="res"></div>
    </div>
    <footer>
        <center>
            <br><p>©2024 created by "your_name"</p>
        </center>
    </footer>
    <!-- FirebaseのSDKをCDNで読み込む -->
    <script src="https://www.gstatic.com/firebasejs/9.1.2/firebase-app-compat.js"></script>
    <script src="https://www.gstatic.com/firebasejs/9.1.2/firebase-database-compat.js"></script>
    <script src="https://www.gstatic.com/firebasejs/9.1.2/firebase-auth-compat.js"></script>
    <script>
        // Firebaseの設定と初期化
        const firebaseConfig = {
            apiKey:"YOUR_APIKEY",
            authDomain: "YOUR_AUTHDOMAIN",
            databaseURL: "YOUR_DATABASEURL",
            projectId: "YOUR_PROJECTID",
            storageBucket: "YOUR_STRAGEBUCKET",
            messagingSenderId: "YOUR_MESSAGINGSENDERID",
            appId: "YOUR_APPID",
            measurementId: "YOUR_MEASUREMENTID"
        };
        const firebaseApp = firebase.initializeApp(firebaseConfig);
        const database = firebaseApp.database();

        // 送信ボタンが押されたときの処理
        function conf() {
            let name = document.getElementById("username").value;
            
            if(name === "your_name") {

                alert("エラー:コンテンツ管理者の名前で投稿することはできません。")
                return;
            }
            let confi = confirm("本サービスでは、プログラムの都合上、一度投稿した内容は取り消すことができません。それでも送信しますか？");
            if (confi) {

            if(text === null) {

                alert("textarea is null.");

            }
                sendMessage();
            } else {
                return;
            }
        }

        // メッセージを送信する関数
        function sendMessage() {
            const username = document.getElementById("username").value || "anonymous";
            const message = document.getElementById("text").value.trim();
            if (message !== '') {
                database.ref('messages').push({
                    username: username,
                    text: message,
                    userId: firebase.auth().currentUser ? firebase.auth().currentUser.uid : null, // 投稿したユーザーのIDを追加
                    timestamp: firebase.database.ServerValue.TIMESTAMP
                });
                document.getElementById("text").value = ''; // メッセージ送信後、入力欄を空にする
            }
        }

        // チャットメッセージを表示するリスナーの設定
        database.ref('messages').orderByChild('timestamp').on('child_added', snapshot => {
            const message = snapshot.val();
            const chatBox = document.getElementById('res');
            const messageElement = document.createElement('div');
            messageElement.innerText = `${message.username}: ${message.text}`;
            chatBox.prepend(messageElement); // prependを使用して新しいメッセージを上に表示
        });

    </script>
</body>
</html>
```
これでプログラムは作成が終わりました。
## 最後に
今回はfirebaseという外部APIを使用してチャットシステムを作りました。ちなみに今回も修正とfirebaseの導入をgptにやってもらいました。ただ、databaseurlの確認方法がわからないので、誰か確認方法がわかるという方はコメントで教えてくれると嬉しいです。
それではまたお会いしましょう！