Skip to main content
Mirage’s chat room feature enables real-time group conversations with support for both public and private rooms, password protection, and temporary message storage.

Creating a Chat Room

Create your own chat room to start conversations with other Mirage users.
1

Choose Room Type

Decide between public or private:
  • Public Rooms: Discoverable by all users, anyone can join
  • Private Rooms: Require a password to join, invite-only
2

Name Your Room

Choose a unique name for your room (must not already exist)
3

Set Password (Private Only)

For private rooms, create a secure password that you’ll share with intended members
4

Room Created

You’re automatically added as the first member and can start inviting others

Room Creation Code

app/routes/chat.py:13-70
@chat_bp.route('/api/create_room', methods=['POST'])
def create_room():
    data = request.get_json()
    room_name = data.get('room_name', '').strip()
    is_private = int(data.get('is_private', 0))
    password = data.get('password', '').strip() if is_private else None
    token = request.headers.get('Authorization')

    # Validate token and user
    c.execute('SELECT username FROM users WHERE token=?', (token,))
    user = c.fetchone()
    if not user:
        return jsonify({'error': "unauthorized"}), 401

    # Check if room already exists
    c.execute('SELECT id FROM rooms WHERE name=?', (room_name,))
    if c.fetchone():
        return jsonify({'error': "room already exists"}), 400

    # Hash password if private
    pw_hash = hash_pw(password) if is_private else None

    # Create room and add creator as first member
    c.execute('INSERT INTO rooms (name, is_private, password_hash) VALUES (?, ?, ?)', (room_name, is_private, pw_hash))
    room_id = c.lastrowid
    c.execute('INSERT INTO room_members (room_id, username) VALUES (?, ?)', (room_id, user[0]))
Public Room Limit: Mirage allows a maximum of 5 public rooms to maintain server performance. Consider creating a private room if you reach this limit.

Joining Rooms

Discover and join existing chat rooms to participate in conversations.
Browse the list of public rooms and join with a single click:
app/routes/chat.py:195-225
@chat_bp.route('/api/rooms', methods=['GET'])
def list_rooms():
    # Get all public rooms
    c.execute('SELECT id, name FROM rooms WHERE is_private=0')
    rooms = c.fetchall()
    
    # Check which rooms user is already in
    c.execute('SELECT room_id FROM room_members WHERE username=?', (user[0],))
    user_rooms_set = {r[0] for r in c.fetchall()}
    
    data = []
    for room_id, name in rooms:
        data.append({
            'room_id': room_id,
            'name': name,
            'joined': room_id in user_rooms_set
        })

Sending Messages

Participate in room conversations with real-time messaging.

Message Flow

  1. Compose your message (text content)
  2. System verifies you’re a room member
  3. Message is stored in memory with timestamp
  4. All room members can see the message instantly
  5. Messages expire after the configured lifespan
app/routes/chat.py:126-167
@chat_bp.route('/api/send_room_message', methods=['POST'])
def send_room_message():
    data = request.get_json()
    token = request.headers.get('Authorization')
    room_id = data.get('room_id')
    message = data.get('message', '').strip()

    # Verify user is in the room
    c.execute('SELECT id FROM room_members WHERE room_id=? AND username=?', (room_id, user[0]))
    if not c.fetchone():
        return jsonify({'error': 'you are not in this room'}), 403

    # Create message with timestamp
    message_data = {
        'username': user[0],
        'message': message,
        'created_at': time.time(),
        'room_id': room_id
    }

    # Add to message queue
    messages.append(message_data)
    
    # Clean old messages (keep only recent ones)
    now = time.time()
    messages[:] = [m for m in messages if now - m['created_at'] < MESSAGE_LIFESPAN]
    if len(messages) > MAX_MESSAGES:
        messages.pop(0)

Message Storage Configuration

app/config.py:4-7
DB_FILE = "db.sqlite"
MAX_MESSAGES = 100          # Maximum messages in memory
MESSAGE_LIFESPAN = 60 * 30 * 30  # 54,000 seconds (~15 hours)
MESSAGES_FILE = "messages.txt"    # Persistent storage backup
Messages are stored in memory for performance and automatically expire after 15 hours. The system maintains a maximum of 100 messages at a time.

Retrieving Messages

View the message history for any room you’re a member of.
app/routes/chat.py:169-193
@chat_bp.route('/api/get_room_messages', methods=['GET'])
def get_room_messages():
    token = request.headers.get('Authorization')
    room_id = request.args.get('room_id')

    # Verify user is in the room
    c.execute('SELECT id FROM room_members WHERE room_id=? AND username=?', (room_id, user[0]))
    if not c.fetchone():
        return jsonify({'error': 'you are not in this room'}), 403

    # Filter messages for this room
    filtered = [m for m in messages if str(m.get('room_id')) == str(room_id)]
    return jsonify({'messages': filtered}), 200

Room Members

View who’s in a room and manage your room memberships.

View Members

See all current members of any room you’ve joined
app/routes/chat.py:227-250
@chat_bp.route('/api/room_members/<int:room_id>', methods=['GET'])
def get_room_members(room_id):
    c.execute('SELECT username FROM room_members WHERE room_id=?', (room_id,))
    members = c.fetchall()
    members_list = [m[0] for m in members]
    return jsonify({'members': members_list}), 200

Auto-Join on Create

Room creators are automatically added as the first member when the room is created

Database Schema

app/db.py:89-103
CREATE TABLE IF NOT EXISTS rooms (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT UNIQUE NOT NULL,
  is_private INTEGER DEFAULT 0,
  password_hash TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)

CREATE TABLE IF NOT EXISTS room_members (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  room_id INTEGER NOT NULL,
  username TEXT NOT NULL,
  joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY(room_id) REFERENCES rooms(id),
  FOREIGN KEY(username) REFERENCES users(username)
)

Real-Time Features

The chat system includes automatic server ping to maintain connections:
app/routes/chat.py:128-129
ping_thread = threading.Thread(target=ping_server, args=(60,), daemon=True)
ping_thread.start()
Messages are periodically saved to disk as a backup:
save_messages(messages)  # Writes to MESSAGES_FILE
Old messages are automatically removed to maintain performance:
  • Messages older than MESSAGE_LIFESPAN are deleted
  • Only the most recent MAX_MESSAGES are kept

API Endpoints

Create Room

Start a new chat room

Join Room

Enter an existing room

List Rooms

Browse public rooms

Send Message

Post to room chat

Get Messages

View room history

Room Members

See who’s in a room

Build docs developers (and LLMs) love