From 0f8230508763b020bf3e66c281aacee07c8bcd88 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Sat, 23 Nov 2024 11:32:49 -0500 Subject: [PATCH] feature complete. "sorry for the convenience" modified: app.py new file: migrations/versions/1ac5a8e0f577_user_session_table.py --- app.py | 48 +++++++++++++++---- .../1ac5a8e0f577_user_session_table.py | 32 +++++++++++++ 2 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 migrations/versions/1ac5a8e0f577_user_session_table.py diff --git a/app.py b/app.py index 7b9201a..3123d3a 100644 --- a/app.py +++ b/app.py @@ -25,7 +25,7 @@ from flask import ( Response, ) -from flask_socketio import SocketIO, emit, join_room +from flask_socketio import SocketIO, emit, join_room, leave_room from flask_sqlalchemy import SQLAlchemy from sqlalchemy.exc import InvalidRequestError @@ -187,6 +187,14 @@ class Room(db.Model): return self.active_users.split(",") if self.active_users else [] +class UserSession(db.Model): + id = db.Column(db.Integer, primary_key=True) + session_id = db.Column(db.String(128), unique=True, nullable=False) + username = db.Column(db.String(128)) + room_name = db.Column(db.String(128)) + room_id = db.Column(db.Integer) + + class Message(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(128), nullable=False) @@ -442,12 +450,20 @@ def search_messages(keywords): return search_results_list +# Handle user joining a room @socketio.on("join") def on_join(data): room_name = data["room_name"] + username = data["username"] room = get_room(room_name) - room.add_user(data["username"]) + room.add_user(username) + + # Store session data in the database + user_session = UserSession( + session_id=request.sid, username=username, room_name=room_name, room_id=room.id + ) + db.session.add(user_session) # Emit the active users list to the new joiner emit("active_users", {"users": room.get_active_users()}, room=request.sid) @@ -473,9 +489,6 @@ def on_join(data): total_token_count = 0 # Send the history of messages only to the newly connected client. - # The reason for using `request.sid` here is to target the specific session (or client) that - # just connected, so only they receive the backlog of messages, rather than broadcasting - # this information to all clients in the room. for message in previous_messages: if not message.is_base64_image(): total_token_count += message.token_count @@ -494,18 +507,17 @@ def on_join(data): room.title = gpt_generate_room_title(previous_messages) db.session.add(room) socketio.emit("update_room_title", {"title": room.title}, room=room.name) - # Emit an event to update this rooms title in the sidebar for all users. + # Emit an event to update this room's title in the sidebar for all users. updated_room_data = {"id": room.id, "name": room.name, "title": room.title} socketio.emit("update_room_list", updated_room_data, room=None) - # commit the active user list and title to database. + # commit session & active user list and title to database. db.session.commit() # Broadcast to all clients in the room that a new user has joined. - # Here, `room=room` ensures the message is sent to everyone in that specific room. emit( "chat_message", - {"id": None, "content": f"{data['username']} has joined the room."}, + {"id": None, "content": f"{username} has joined the room."}, room=room.name, ) emit( @@ -518,6 +530,24 @@ def on_join(data): ) +# Handle user leaving a room +@socketio.on("disconnect") +def on_disconnect(): + sid = request.sid + user_session = UserSession.query.filter_by(session_id=sid).first() + + if user_session: + room_name = user_session.room_name + username = user_session.username + room = Room.query.filter_by(name=room_name).first() + room.remove_user(username) + leave_room(room_name) + emit("active_users", {"users": room.get_active_users()}, room=room_name) + # Remove session data from the database + db.session.delete(user_session) + db.session.commit() + + @socketio.on("chat_message") def handle_message(data): room_name = data["room_name"] diff --git a/migrations/versions/1ac5a8e0f577_user_session_table.py b/migrations/versions/1ac5a8e0f577_user_session_table.py new file mode 100644 index 0000000..f49e9c3 --- /dev/null +++ b/migrations/versions/1ac5a8e0f577_user_session_table.py @@ -0,0 +1,32 @@ +"""user session table + +Revision ID: 1ac5a8e0f577 +Revises: 38a330686a17 +Create Date: 2024-11-23 11:25:01.723169 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import sqlite + +# revision identifiers, used by Alembic. +revision = '1ac5a8e0f577' +down_revision = '38a330686a17' +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table('user_session', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('session_id', sa.String(length=128), nullable=False), + sa.Column('username', sa.String(length=128), nullable=True), + sa.Column('room_name', sa.String(length=128), nullable=True), + sa.Column('room_id', sa.Integer(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('session_id') + ) + + +def downgrade(): + op.drop_table('user_session')