Files
jackboxpartypack-gamepicker/docs/SESSION_END_WEBSOCKET.md

307 lines
8.2 KiB
Markdown
Raw Normal View History

2025-11-02 16:06:31 -05:00
# Session End WebSocket Event
This document describes the `session.ended` WebSocket event that is broadcast when a game session is closed.
## 📋 Event Overview
When a session is closed (either manually or through timeout), the backend broadcasts a `session.ended` event to all subscribed WebSocket clients. This allows bots and other integrations to react immediately to session closures.
## 🔌 WebSocket Connection
**Endpoint:** `ws://localhost:5000/api/sessions/live`
**Authentication:** Required (JWT token)
## 📨 Event Format
### Event Type
```
session.ended
```
### Full Message Structure
```json
{
"type": "session.ended",
"timestamp": "2025-11-01T02:30:45.123Z",
"data": {
"session": {
"id": 17,
"is_active": 0,
"games_played": 5
}
}
}
```
### Field Descriptions
| Field | Type | Description |
|-------|------|-------------|
| `type` | string | Always `"session.ended"` |
| `timestamp` | string | ISO 8601 timestamp when the event was generated |
| `data.session.id` | number | The ID of the session that ended |
| `data.session.is_active` | number | Always `0` (inactive) for ended sessions |
| `data.session.games_played` | number | Total number of games played in the session |
## 🚀 Implementation
### Backend Implementation
The `session.ended` event is automatically broadcast when:
1. **Manual Session Close**: Admin closes a session via `POST /api/sessions/:id/close`
2. **Session Timeout**: (If implemented) When a session times out
**Code Location:** `backend/routes/sessions.js` - `POST /:id/close` endpoint
```javascript
// Broadcast session.ended event via WebSocket
const wsManager = getWebSocketManager();
if (wsManager) {
const eventData = {
session: {
id: closedSession.id,
is_active: 0,
games_played: closedSession.games_played
}
};
wsManager.broadcastEvent('session.ended', eventData, parseInt(req.params.id));
}
```
### Client Implementation Example
#### Node.js with `ws` library
```javascript
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 session
ws.send(JSON.stringify({
type: 'subscribe',
sessionId: 17
}));
break;
case 'session.ended':
console.log('Session ended!');
console.log(`Session ID: ${message.data.session.id}`);
console.log(`Games played: ${message.data.session.games_played}`);
// Handle session end (e.g., announce in IRC, Discord, etc.)
break;
}
});
```
#### Python with `websockets` library
```python
import asyncio
import json
import websockets
async def listen_for_session_end():
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":
# Subscribe to session
await websocket.send(json.dumps({
"type": "subscribe",
"sessionId": 17
}))
elif data["type"] == "session.ended":
session = data["data"]["session"]
print(f"Session {session['id']} ended!")
print(f"Games played: {session['games_played']}")
# Handle session end
asyncio.run(listen_for_session_end())
```
## 🧪 Testing
### Using the Test Script
A test script is provided to verify the `session.ended` event:
```bash
node ../tests/test-session-end-websocket.js <session_id> <jwt_token>
2025-11-02 16:06:31 -05:00
```
**Example:**
```bash
node ../tests/test-session-end-websocket.js 17 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
2025-11-02 16:06:31 -05:00
```
### Manual Testing Steps
1. **Start the backend server:**
```bash
cd backend
npm start
```
2. **Run the test script in another terminal:**
```bash
node ../tests/test-session-end-websocket.js 17 <your-jwt-token>
2025-11-02 16:06:31 -05:00
```
3. **Close the session in the Picker UI** or via API:
```bash
curl -X POST http://localhost:5000/api/sessions/17/close \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json"
```
4. **Verify the event is received** in the test script output
### Expected Output
```
🚀 Testing session.ended WebSocket event
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📡 Connecting to: ws://localhost:5000/api/sessions/live
🎮 Session ID: 17
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Connected to WebSocket server
🔐 Authenticating...
✅ Authentication successful
📻 Subscribing to session 17...
✅ Subscribed to session 17
👂 Listening for session.ended events...
(Close the session in the Picker to trigger the event)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎉 SESSION.ENDED EVENT RECEIVED!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 Event Data:
{
"type": "session.ended",
"timestamp": "2025-11-01T02:30:45.123Z",
"data": {
"session": {
"id": 17,
"is_active": 0,
"games_played": 5
}
}
}
✨ Event Details:
Session ID: 17
Active: No
Games Played: 5
Timestamp: 2025-11-01T02:30:45.123Z
✅ Test successful! The bot should now announce the session end.
```
## 🤖 Bot Integration
### IRC/Kosmi Bot Example
When the bot receives a `session.ended` event, it should:
1. **Announce the final vote counts** for the last game played
2. **Announce that the game night has ended**
3. **Optionally display session statistics**
Example bot response:
```
🗳️ Final votes for Quiplash 3: 5👍 1👎 (Score: +4)
🌙 Game Night has ended! Thanks for playing!
📊 Session Stats: 5 games played
```
### Fallback Behavior
The bot should also implement **polling detection** as a fallback in case the WebSocket connection fails or the event is not received:
- Poll `GET /api/sessions/active` every 30 seconds
- If a previously active session becomes inactive, treat it as a session end
- This ensures the bot will always detect session endings, even without WebSocket
## 🔍 Debugging
### Check WebSocket Logs
The backend logs WebSocket events:
```
[WebSocket] Client subscribed to session 17
[Sessions] Broadcasted session.ended event for session 17
[WebSocket] Broadcasted session.ended to 1 client(s) for session 17
```
### Common Issues
1. **Event not received:**
- Verify the client is authenticated (`auth_success` received)
- Verify the client is subscribed to the correct session
- Check backend logs for broadcast confirmation
2. **Connection drops:**
- Implement ping/pong heartbeat (send `{"type": "ping"}` every 30s)
- Handle reconnection logic in your client
3. **Multiple events received:**
- This is normal if multiple clients are subscribed
- Each client receives its own copy of the event
## 📚 Related Documentation
- [WebSocket Testing Guide](WEBSOCKET_TESTING.md)
- [Bot Integration Guide](BOT_INTEGRATION.md)
- [API Quick Reference](API_QUICK_REFERENCE.md)
## 🔗 Related Events
| Event Type | Description | When Triggered |
|------------|-------------|----------------|
| `session.started` | A new session was created | When session is created |
| `game.added` | A new game was added to the session | When a game starts |
| `session.ended` | The session has ended | When session is closed |
| `vote.received` | A vote was cast for a game | When a user votes |
## 📝 Notes
- The `session.ended` event is broadcast to **all clients subscribed to that session**
- The event includes the final `games_played` count for the session
- The `is_active` field will always be `0` for ended sessions
- The timestamp is in ISO 8601 format with timezone (UTC)