openchat / app.py
triflix's picture
Update app.py
274fa58 verified
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 and WebSocket Initialization ---
app = FastAPI()
# Use the system's writable /tmp directory for data storage
TMP_DIR = Path("/tmp")
CHAT_FILE = TMP_DIR / "chat_history.json"
# Create an ASGI-compatible Socket.IO server
sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins=[])
# Wrap the FastAPI app with the Socket.IO middleware
socket_app = socketio.ASGIApp(sio, app)
# Mount static files (for CSS)
app.mount("/static", StaticFiles(directory="static"), name="static")
# --- Helper Functions for Data Persistence ---
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)
# --- WebSocket Event Handlers ---
@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()
}
# Update and save history
history = load_chat_history()
history.append(new_message)
save_chat_history(history)
print(f"MESSAGE from {user_id}: {data['message']}")
# Broadcast the new message to everyone
await sio.emit('new_message', new_message)
@sio.event
def disconnect(sid):
"""Handles a client disconnection."""
print(f"DISCONNECT: {sid}")
# --- FastAPI Endpoint to Serve the HTML Page ---
@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())