feat; websocket preparation

This commit is contained in:
akhdanre 2025-05-05 19:01:52 +07:00
parent 297c84709d
commit fa971e1d24
4 changed files with 101 additions and 10 deletions

0
app/blueprints/socket.py Normal file
View File

View File

@ -3,6 +3,7 @@ from .user_controller import UserController
from .quiz_controller import QuizController from .quiz_controller import QuizController
from .history_controller import HistoryController from .history_controller import HistoryController
from .subject_controller import SubjectController from .subject_controller import SubjectController
from .socket_conroller import SocketController
__all__ = [ __all__ = [
"AuthController", "AuthController",
@ -10,4 +11,5 @@ __all__ = [
"QuizController", "QuizController",
"HistoryController", "HistoryController",
"SubjectController", "SubjectController",
"SocketController",
] ]

View File

@ -0,0 +1,82 @@
from flask_socketio import SocketIO, emit, join_room, leave_room
from flask import request
class SocketController:
def __init__(self, socketio: SocketIO):
self.socketio = socketio
self.rooms = {} # room_name -> set of sids
self._register_events()
def _register_events(self):
@self.socketio.on("connect")
def on_connect():
print(f"Client connected: {request.sid}")
emit("connection_response", {"status": "connected", "sid": request.sid})
@self.socketio.on("disconnect")
def on_disconnect():
sid = request.sid
# Remove user from all rooms they joined
for room, members in self.rooms.items():
if sid in members:
members.remove(sid)
emit(
"room_message",
{"message": f"A user has disconnected.", "room": room},
room=room,
)
print(f"Client disconnected: {sid}")
@self.socketio.on("join_room")
def handle_join_room(data):
if not isinstance(data, dict):
emit("error", {"message": "Invalid data format"})
return
room = data.get("room")
username = data.get("username", "anonymous")
sid = request.sid
# Create room if it doesn't exist
if room not in self.rooms:
self.rooms[room] = set()
# Check if room has space
if len(self.rooms[room]) >= 2:
emit("room_full", {"message": "Room is full. Max 2 users allowed."})
return
# Join room
self.rooms[room].add(sid)
join_room(room)
emit(
"room_message",
{"message": f"{username} has joined the room.", "room": room},
room=room,
)
@self.socketio.on("leave_room")
def handle_leave_room(data):
room = data.get("room")
username = data.get("username", "anonymous")
sid = request.sid
if room in self.rooms and sid in self.rooms[room]:
self.rooms[room].remove(sid)
leave_room(room)
print(f"{username} left room {room}")
emit(
"room_message",
{"message": f"{username} has left the room.", "room": room},
room=room,
)
@self.socketio.on("send_message")
def on_send_message(data):
room = data.get("room")
message = data.get("message")
username = data.get("username", "anonymous")
print(f"[{room}] {username}: {message}")
emit("receive_message", {"message": message, "from": username}, room=room)

View File

@ -1,11 +1,17 @@
import eventlet
eventlet.monkey_patch()
import sys import sys
import os import os
import logging
from flask import Flask, request
from flask_socketio import SocketIO
sys.path.append(os.path.dirname(__file__)) sys.path.append(os.path.dirname(__file__))
from di_container import Container from di_container import Container
from configs import Config, LoggerConfig from configs import Config, LoggerConfig
from flask import Flask
from blueprints import ( from blueprints import (
auth_blueprint, auth_blueprint,
user_blueprint, user_blueprint,
@ -13,9 +19,13 @@ from blueprints import (
default_blueprint, default_blueprint,
history_blueprint, history_blueprint,
subject_blueprint, subject_blueprint,
socket,
) )
from database import init_db from database import init_db
import logging from controllers import SocketController
socketio = SocketIO(cors_allowed_origins="*")
def createApp() -> Flask: def createApp() -> Flask:
@ -28,13 +38,15 @@ def createApp() -> Flask:
LoggerConfig.init_logger(app) LoggerConfig.init_logger(app)
container = Container() container = Container()
app.container = container app.container = container
mongo = init_db(app) mongo = init_db(app)
if mongo is not None: if mongo is not None:
container.mongo.override(mongo) container.mongo.override(mongo)
SocketController(socketio)
socketio.init_app(app)
container.wire( container.wire(
modules=[ modules=[
"blueprints.auth", "blueprints.auth",
@ -45,7 +57,6 @@ def createApp() -> Flask:
] ]
) )
# Register Blueprints
app.register_blueprint(default_blueprint) app.register_blueprint(default_blueprint)
app.register_blueprint(auth_blueprint, url_prefix="/api") app.register_blueprint(auth_blueprint, url_prefix="/api")
app.register_blueprint(user_blueprint, url_prefix="/api") app.register_blueprint(user_blueprint, url_prefix="/api")
@ -53,14 +64,10 @@ def createApp() -> Flask:
app.register_blueprint(history_blueprint, url_prefix="/api/history") app.register_blueprint(history_blueprint, url_prefix="/api/history")
app.register_blueprint(subject_blueprint, url_prefix="/api/subject") app.register_blueprint(subject_blueprint, url_prefix="/api/subject")
# for rule in app.url_map.iter_rules():
# print(f"Route: {rule} -> Methods: {rule.methods}")
return app return app
# app = createApp()
if __name__ == "__main__": if __name__ == "__main__":
app = createApp() app = createApp()
app.run(host="0.0.0.0", debug=Config.DEBUG)
socketio.run(app, host="0.0.0.0", port=5000, debug=Config.DEBUG)