Files
jackboxpartypack-gamepicker/SESSION_START_WEBSOCKET.md
2025-11-02 16:06:31 -05:00

9.7 KiB

Session Start WebSocket Event

This document describes the session.started WebSocket event that is broadcast when a new game session is created.

📋 Event Overview

When a new session is created, the backend broadcasts a session.started event to all subscribed WebSocket clients. This allows bots and other integrations to react immediately to new game sessions.

🔌 WebSocket Connection

Endpoint: ws://localhost:5000/api/sessions/live

Authentication: Required (JWT token)

📨 Event Format

Event Type

session.started

Full Message Structure

{
  "type": "session.started",
  "timestamp": "2025-11-01T20:00:00.123Z",
  "data": {
    "session": {
      "id": 17,
      "is_active": 1,
      "created_at": "2025-11-01T20:00:00.123Z",
      "notes": "Friday Game Night"
    }
  }
}

Field Descriptions

Field Type Description
type string Always "session.started"
timestamp string ISO 8601 timestamp when the event was generated
data.session.id number The ID of the newly created session
data.session.is_active number Always 1 (active) for new sessions
data.session.created_at string ISO 8601 timestamp when the session was created
data.session.notes string/null Optional notes for the session

🚀 Implementation

Backend Implementation

The session.started event is automatically broadcast when:

  1. New Session Created: Admin creates a session via POST /api/sessions

Code Location: backend/routes/sessions.js - POST / endpoint

// Broadcast session.started event via WebSocket
const wsManager = getWebSocketManager();
if (wsManager) {
  const eventData = {
    session: {
      id: newSession.id,
      is_active: 1,
      created_at: newSession.created_at,
      notes: newSession.notes
    }
  };
  
  wsManager.broadcastEvent('session.started', eventData, parseInt(newSession.id));
}

Client Implementation Example

Node.js with ws library

const WebSocket = require('ws');

const ws = new WebSocket('ws://localhost:5000/api/sessions/live');

ws.on('open', () => {
  // Authenticate
  ws.send(JSON.stringify({
    type: 'auth',
    token: 'your-jwt-token'
  }));
});

ws.on('message', (data) => {
  const message = JSON.parse(data.toString());
  
  switch (message.type) {
    case 'auth_success':
      // Subscribe to the new session (or subscribe when you receive session.started)
      ws.send(JSON.stringify({
        type: 'subscribe',
        sessionId: 17
      }));
      break;
      
    case 'session.started':
      console.log('New session started!');
      console.log(`Session ID: ${message.data.session.id}`);
      console.log(`Created at: ${message.data.session.created_at}`);
      if (message.data.session.notes) {
        console.log(`Notes: ${message.data.session.notes}`);
      }
      
      // Auto-subscribe to the new session
      ws.send(JSON.stringify({
        type: 'subscribe',
        sessionId: message.data.session.id
      }));
      break;
  }
});

Python with websockets library

import asyncio
import json
import websockets

async def listen_for_session_start():
    uri = "ws://localhost:5000/api/sessions/live"
    
    async with websockets.connect(uri) as websocket:
        # Authenticate
        await websocket.send(json.dumps({
            "type": "auth",
            "token": "your-jwt-token"
        }))
        
        async for message in websocket:
            data = json.loads(message)
            
            if data["type"] == "auth_success":
                print("Authenticated, waiting for sessions...")
                
            elif data["type"] == "session.started":
                session = data["data"]["session"]
                print(f"🎮 New session started! ID: {session['id']}")
                print(f"📅 Created: {session['created_at']}")
                if session.get('notes'):
                    print(f"📝 Notes: {session['notes']}")
                
                # Auto-subscribe to the new session
                await websocket.send(json.dumps({
                    "type": "subscribe",
                    "sessionId": session["id"]
                }))

asyncio.run(listen_for_session_start())

🧪 Testing

Manual Testing Steps

  1. Start the backend server:

    cd backend
    npm start
    
  2. Connect a WebSocket client (use the test script or your own):

    # You can modify test-session-end-websocket.js to listen for session.started
    
  3. Create a new session in the Picker UI or via API:

    curl -X POST http://localhost:5000/api/sessions \
      -H "Authorization: Bearer <your-jwt-token>" \
      -H "Content-Type: application/json" \
      -d '{"notes": "Friday Game Night"}'
    
  4. Verify the event is received by your WebSocket client

Expected Event

{
  "type": "session.started",
  "timestamp": "2025-11-01T20:00:00.123Z",
  "data": {
    "session": {
      "id": 18,
      "is_active": 1,
      "created_at": "2025-11-01T20:00:00.123Z",
      "notes": "Friday Game Night"
    }
  }
}

🤖 Bot Integration

IRC/Kosmi Bot Example

When the bot receives a session.started event, it should:

  1. Announce the new game session to users
  2. Auto-subscribe to the session to receive game.added and session.ended events
  3. Optionally display session info (notes, ID, etc.)

Example bot response:

🎮 Game Night has started! Session #18
📝 Friday Game Night
🗳️ Vote with thisgame++ or thisgame-- during games!

Implementation Example

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  
  if (msg.type === 'session.started') {
    const { id, notes, created_at } = msg.data.session;
    
    // Announce to IRC/Discord/etc
    bot.announce(`🎮 Game Night has started! Session #${id}`);
    if (notes) {
      bot.announce(`📝 ${notes}`);
    }
    bot.announce('🗳️ Vote with thisgame++ or thisgame-- during games!');
    
    // Auto-subscribe to this session
    ws.send(JSON.stringify({
      type: 'subscribe',
      sessionId: id
    }));
  }
});

🔍 Debugging

Check WebSocket Logs

The backend logs WebSocket events:

[Sessions] Broadcasted session.started event for session 18
[WebSocket] Broadcasted session.started to 1 client(s) for session 18

Common Issues

  1. Event not received:

    • Verify the client is authenticated (auth_success received)
    • Check backend logs for broadcast confirmation
    • No subscription required - All authenticated clients automatically receive session.started events
    • Make sure your WebSocket connection is open and authenticated
  2. Missing session data:

    • Check if the session was created successfully
    • Verify the API response includes all fields
  3. Duplicate events:

    • Normal if multiple clients are connected
    • Each client receives its own copy of the event

🔗 Session Lifecycle Events

session.started
    ↓
game.added (multiple times)
    ↓
vote.received (during each game)
    ↓
session.ended

📝 Notes

  • The session.started event is broadcast to all authenticated clients (not just subscribed ones)
  • No subscription required - All authenticated clients automatically receive this event
  • Clients should auto-subscribe to the new session to receive subsequent game.added and vote.received events
  • The is_active field will always be 1 for new sessions
  • The notes field may be null if no notes were provided
  • The timestamp is in ISO 8601 format with timezone (UTC)

💡 Use Cases

  1. Bot Announcements - Notify users when game night starts
  2. Auto-Subscription - Automatically subscribe to new sessions
  3. Session Tracking - Track all sessions in external systems
  4. Analytics - Log session creation times and frequency
  5. Notifications - Send push notifications to users

🎯 Best Practices

  1. Auto-subscribe to new sessions when you receive session.started
  2. Store the session ID for later reference
  3. Handle reconnections gracefully (you might miss the event)
  4. Use polling as fallback to detect sessions created while disconnected
  5. Validate session data before processing

🔄 Complete Event Flow Example

const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:5000/api/sessions/live');

let currentSessionId = null;

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  
  switch (msg.type) {
    case 'session.started':
      currentSessionId = msg.data.session.id;
      console.log(`🎮 Session ${currentSessionId} started!`);
      
      // Auto-subscribe
      ws.send(JSON.stringify({
        type: 'subscribe',
        sessionId: currentSessionId
      }));
      break;
      
    case 'game.added':
      console.log(`🎲 New game: ${msg.data.game.title}`);
      break;
      
    case 'vote.received':
      console.log(`🗳️ Vote: ${msg.data.vote.type}`);
      break;
      
    case 'session.ended':
      console.log(`🌙 Session ${msg.data.session.id} ended!`);
      console.log(`📊 Games played: ${msg.data.session.games_played}`);
      currentSessionId = null;
      break;
  }
});

Conclusion

The session.started WebSocket event provides instant notification when new game sessions are created, allowing bots and integrations to react immediately and provide a seamless user experience.