|
|
import json |
|
|
import random |
|
|
from pathlib import Path |
|
|
from datetime import datetime |
|
|
|
|
|
import socketio |
|
|
from fastapi import FastAPI |
|
|
from fastapi.requests import Request |
|
|
from fastapi.responses import HTMLResponse |
|
|
from fastapi.staticfiles import StaticFiles |
|
|
|
|
|
|
|
|
app = FastAPI() |
|
|
|
|
|
TMP_DIR = Path("/tmp") |
|
|
CHAT_FILE = TMP_DIR / "chat_history.json" |
|
|
|
|
|
|
|
|
sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins=[]) |
|
|
|
|
|
socket_app = socketio.ASGIApp(sio, app) |
|
|
|
|
|
|
|
|
app.mount("/static", StaticFiles(directory="static"), name="static") |
|
|
|
|
|
|
|
|
def load_chat_history(): |
|
|
"""Loads chat history from the JSON file.""" |
|
|
if not CHAT_FILE.exists(): |
|
|
return [] |
|
|
with open(CHAT_FILE, "r") as f: |
|
|
try: |
|
|
content = f.read() |
|
|
if not content: return [] |
|
|
return json.loads(content) |
|
|
except json.JSONDecodeError: |
|
|
return [] |
|
|
|
|
|
def save_chat_history(data): |
|
|
"""Saves the entire chat history to the JSON file.""" |
|
|
with open(CHAT_FILE, "w") as f: |
|
|
json.dump(data, f, indent=4) |
|
|
|
|
|
|
|
|
|
|
|
@sio.event |
|
|
async def connect(sid, environ): |
|
|
""" |
|
|
Handles a new client connection. |
|
|
- Assigns a random User ID. |
|
|
- Loads chat history. |
|
|
- Sends the history and User ID back to the connecting client. |
|
|
""" |
|
|
user_id = f"User-{random.randint(100000, 999999)}" |
|
|
await sio.save_session(sid, {'user_id': user_id}) |
|
|
print(f"CONNECT: {sid}, User-ID: {user_id}") |
|
|
|
|
|
chat_history = load_chat_history() |
|
|
await sio.emit('load_history', {'history': chat_history, 'user_id': user_id}, to=sid) |
|
|
|
|
|
@sio.event |
|
|
async def chat_message(sid, data): |
|
|
""" |
|
|
Handles an incoming chat message from a client. |
|
|
- Retrieves the user's session data (their user_id). |
|
|
- Creates a new message entry. |
|
|
- Appends it to the chat history file. |
|
|
- Broadcasts the new message to ALL connected clients. |
|
|
""" |
|
|
session = await sio.get_session(sid) |
|
|
user_id = session.get('user_id', 'Anonymous') |
|
|
|
|
|
new_message = { |
|
|
"sender": user_id, |
|
|
"message": data["message"], |
|
|
"timestamp": datetime.now().isoformat() |
|
|
} |
|
|
|
|
|
|
|
|
history = load_chat_history() |
|
|
history.append(new_message) |
|
|
save_chat_history(history) |
|
|
|
|
|
print(f"MESSAGE from {user_id}: {data['message']}") |
|
|
|
|
|
await sio.emit('new_message', new_message) |
|
|
|
|
|
@sio.event |
|
|
def disconnect(sid): |
|
|
"""Handles a client disconnection.""" |
|
|
print(f"DISCONNECT: {sid}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse) |
|
|
async def read_root(request: Request): |
|
|
"""Serves the main index.html file.""" |
|
|
with open("templates/index.html") as f: |
|
|
return HTMLResponse(content=f.read()) |