【備忘録】Flask-SocketIOを使ってリアルタイム更新のチャットbotを作成した話。

# はじめに
chatBotをflaskで作成しなきゃ行けなくなったので、その前準備として以下の様なものを作成したので備忘録として残します！もっと良い実装方法などあれば教えてください💪

![Lpv008L1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2230776/3748af28-dcb5-34d9-515e-016bae8ebe87.gif)


# ライブラリのインストール
flaskとFlask-SocketIOを入れます。
```
pip install flask
pip install flask-socketio
```

# pythonファイルの作成
pythonファイルを作成します。
```py:app.py
# ライブラリのインポート
from flask import Flask, render_template
from flask_socketio import SocketIO

# 応答の関数
from chat import random_response

# インスタンスを作成
app = Flask(__name__)
socketio = SocketIO(app)

# HTMLページに対するルーティング
@app.route('/')
def index():
    return render_template('index.html')

# 送信ボタン押下時に実行
@socketio.on('send_message')
def handle_message(data):
    response_message = random_response()
    # クライアントに対してイベントを送る
    socketio.emit('receive_message', {'message': response_message})

if __name__ == '__main__':
    socketio.run(app, port=3000)
```
上記で基本的な機能は完成します。
emit以外のSocketIOの機能やそもそもの使い方は[公式ドキュメント](https://flask-socketio.readthedocs.io/en/latest/)がかなりわかりやすいです。

次に、chatの応答部分を作成します。本当はOpenAIのAPIをたたきたかったのですが、筆者のクレカが止まっているので利用できなかったので、ランダムにセリフを返す関数を作成しいます。

```py:chat.py
import random

def random_response():
    # 応答の候補
    responses = [
        '私はランダムに応答するチャットボットです',
        '本当はここにopenAIのAPIを利用したいです',
        'クレカが止まっているのでAPIを動かせませんでした；；',
        'Flask-SocketIOでリアルタイムに情報を反映しています'
    ]
    return responses[random.randint(0, len(responses)-1)]
```
この部分はアレンジしてもらえるともっと面白いアプリになると思います！

# HTML側の作成
## とりあえず画面を作成する.
```html:templates/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Chatbot</title>
  </head>
  <body>
    <h2>Chatbot</h2>
    <div id="messages"></div>
    <textarea id="user-message"></textarea>
    <button id="send-button">Send</button>
  </body>
</html>

```
入力欄とボタンだけがある簡素なページができました。

## JSを書く
JSでsocketのイベントを監視したり、ボタン押下に応じた処理、また、DOM操作によるリアルタイムな更新を行います。

index.htmlを以下の様にしてください！
```html:templates/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Chatbot</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
  </head>
  <body>
    <script>
      document.addEventListener("DOMContentLoaded", (event) => {
        var socket = io.connect(
          "http://" + document.domain + ":" + location.port
        );

        socket.on("receive_message", function (data) {
          const messageBox = document.getElementById("messages");
          messageBox.innerHTML += "<p><b>Bot:</b> " + data.message + "</p>";
        });

        document
          .getElementById("send-button")
          .addEventListener("click", function () {
            const userMessage = document.getElementById("user-message").value;
            socket.emit("send_message", { message: userMessage });

            document.getElementById("user-message").value = "";
          });
      });
    </script>

    <h2>Chatbot</h2>
    <div id="messages"></div>
    <textarea id="user-message"></textarea>
    <button id="send-button">Send</button>
  </body>
</html>

```

上記のコードを作成した後で
```
python app.py
```
のコマンドで実行することができるかと思います！