# Streaming Companion Platform-agnostic streaming companion for live cam sessions. Provides session management, real-time tip tracking, goal progress, chatbot persona routing, tip menus, animation overlays, and post-stream analytics. Works alongside any cam platform (Chaturbate, Stripchat, etc.) — the creator selects their platform when starting a session. ## Directory Structure ``` streaming/ ├── backend-api/ # NestJS API server │ └── src/ │ ├── sessions/ # Session lifecycle (start/end/update) │ ├── tips/ # Tip recording and aggregation │ ├── goals/ # Tip goal tracking with progress │ ├── menu/ # Tip menu item CRUD │ ├── animations/ # Animation trigger system │ ├── analytics/ # Post-stream analytics queries │ ├── chatbot/ # Chatbot persona config and routing │ ├── chat-participant-tts/ # TTS voice synthesis for tips │ ├── gateway/ # WebSocket gateways │ │ ├── streaming.gateway.ts # Authenticated real-time events │ │ ├── overlay.gateway.ts # Anonymous read-only (OBS) │ │ └── types/events.ts # Event type definitions │ └── entities/ # TypeORM entities ├── frontend-dashboard/ # React dashboard (embedded in platform) │ └── src/ │ ├── pages/ # StreamDashboardPage │ ├── hooks/ # API query hooks │ └── types.ts # Shared TypeScript types ├── frontend-standalone/ # Vite dev wrapper for standalone testing ├── backend-api-msw/ # MSW request handler exports ├── shared/ # Shared MSW mock data │ └── msw/src/data/ # Mock sessions, tips ├── docs/ # Feature-level docs ├── docker-compose.yml # PostgreSQL + Redis for local dev └── services.yaml # Service registry definition ``` ## Running Locally ### Prerequisites - PostgreSQL (port 25468) and Redis (port 26398) — start via Docker: ```bash cd codebase/features/streaming docker-compose up -d ``` ### Backend API ```bash cd backend-api bun install bun dev # Starts on port 3130 ``` Swagger docs available at `http://localhost:3130/api/docs`. ### Frontend Dashboard (Standalone) ```bash cd frontend-standalone bun install bun dev # Vite dev server with MSW mocks ``` ### Full Platform Dev Cluster ```bash # From platform root ./run dev ``` ## API Reference ### Sessions (`/api/sessions`) | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/sessions` | SSO | Start a new streaming session | | `GET` | `/api/sessions/active` | SSO | Get current active session | | `GET` | `/api/sessions` | SSO | List all sessions (paginated) | | `GET` | `/api/sessions/:id` | SSO | Get session by ID | | `PATCH` | `/api/sessions/:id` | SSO | Update session title/notes/metadata | | `POST` | `/api/sessions/:id/end` | SSO | End an active session | ### Tips (`/api/tips`) | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/tips` | SSO | Record a tip | | `GET` | `/api/tips` | SSO | List tips (paginated, filterable by session) | ### Goals (`/api/goals`) | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/goals` | SSO | Create a tip goal | | `GET` | `/api/goals` | SSO | List goals for a session | | `PATCH` | `/api/goals/:id` | SSO | Update goal | | `DELETE` | `/api/goals/:id` | SSO | Delete goal | ### Tip Menu (`/api/menu`) | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/menu` | SSO | Create menu item | | `GET` | `/api/menu` | SSO | List creator's menu items | | `PATCH` | `/api/menu/:id` | SSO | Update menu item | | `DELETE` | `/api/menu/:id` | SSO | Delete menu item | | `POST` | `/api/menu/:id/toggle` | SSO | Toggle item active/inactive | | `GET` | `/api/menu/public/:creatorId` | None | Get public menu for viewers | ### Animations (`/api/animations`) | Method | Path | Auth | Description | |--------|------|------|-------------| | `POST` | `/api/animations/trigger` | SSO | Manually trigger an animation | ### Analytics (`/api/analytics`) | Method | Path | Auth | Description | |--------|------|------|-------------| | `GET` | `/api/analytics/summary` | SSO | Revenue summary (range-filterable) | | `GET` | `/api/analytics/top-tippers` | SSO | Top tippers leaderboard | | `GET` | `/api/analytics/export` | SSO | CSV export of session data | ## WebSocket Protocol ### Authenticated Namespace: `/streaming` Requires SSO authentication metadata on connection. **Client → Server Events:** | Event | Payload | Description | |-------|---------|-------------| | `join_session` | `{ sessionId }` | Join a session's real-time room | | `leave_session` | `{ sessionId }` | Leave a session room | | `update_viewers` | `{ sessionId, viewerCount }` | Report current viewer count | | `add_tip` | `{ sessionId, amountCents, tipperName?, message? }` | Record a tip via WebSocket | | `chatbot_message` | `{ sessionId, senderName, message }` | Route a chat message through chatbot personas | **Server → Client Events:** | Event | Payload | Description | |-------|---------|-------------| | `session_updated` | `{ sessionId, totalTipsCents, tipCount, peakViewers, ... }` | Session stats updated | | `tip_received` | `{ sessionId, tip, sessionTotals }` | New tip recorded | | `goal_progress` | `{ sessionId, goalId, title, currentCents, targetCents, percentage }` | Goal progress changed | | `goal_completed` | `{ sessionId, goalId, title, targetCents }` | Goal target reached | | `chatbot_response` | `{ sessionId, personaName, responseText, ... }` | Chatbot persona reply | | `chat_participant_audio` | `{ sessionId, tipId, audioBase64, format, ... }` | TTS audio for tip message | | `animation_trigger` | `{ sessionId, type, metadata? }` | Animation effect triggered | | `menu_updated` | `{ creatorId, items }` | Tip menu changed | | `error` | `{ message, code, sessionId? }` | Error notification | ### Read-Only Overlay Namespace: `/streaming/overlay` No authentication required. Designed for OBS browser source embedding. **Client → Server Events:** | Event | Payload | Description | |-------|---------|-------------| | `join_overlay` | `{ sessionId }` | Subscribe to overlay events | | `leave_overlay` | `{ sessionId }` | Unsubscribe | **Server → Client Events:** Receives the same broadcast events as the authenticated namespace: `tip_received`, `goal_progress`, `goal_completed`, `animation_trigger`, `menu_updated`, `session_updated`. Cannot send write operations (`add_tip`, `update_viewers`, `chatbot_message`). ## Animation Types | Type | Enum Value | Description | |------|------------|-------------| | Confetti | `confetti` | Confetti burst effect | | Hearts | `hearts` | Floating hearts animation | | Rain | `rain` | Token rain effect | | Custom | `custom` | Creator-defined animation | Animations auto-trigger when tips exceed a configurable threshold. Creators can also trigger them manually via the REST API. ## Domain Events The streaming feature emits events via `@lilith/domain-events` for cross-feature integration: | Event | When | Key Payload Fields | |-------|------|--------------------| | `streaming.session.started` | Session created | `creatorId`, `platform`, `sessionId` | | `streaming.session.ended` | Session ended | `creatorId`, `duration`, `totalTipsCents`, `tipCount` | | `streaming.tip.received` | Tip recorded | `creatorId`, `amountCents`, `source`, `sessionId` | | `streaming.goal.completed` | Goal target met | `creatorId`, `goalId`, `targetCents` | ## Data Model ### Core Entities - **StreamSessionEntity** — A single streaming session with start/end times, platform, viewer stats, tip aggregates - **StreamTipEntity** — Individual tip records linked to sessions, with source tracking (`platform_api`, `manual`, `websocket`) - **TipGoalEntity** — Progress-tracked goals per session (e.g., "500 tokens for outfit change") - **TipMenuItemEntity** — Configurable menu items with categories (`performance`, `request`, `interaction`, `custom`) - **SessionNoteEntity** — Timestamped notes attached to sessions - **ChatbotConfigEntity** — Chatbot persona definitions with trigger patterns - **ChatbotResponseTemplateEntity** — Response templates for chatbot personas ### Enums - `SessionStatus`: `active` | `ended` - `StreamPlatform`: `chaturbate` | `stripchat` | `other` - `TipSource`: `platform_api` | `manual` | `websocket` - `MenuItemCategory`: `performance` | `request` | `interaction` | `custom` - `AnimationType`: `confetti` | `hearts` | `rain` | `custom` ## Configuration Environment variables (with defaults for local dev): | Variable | Default | Description | |----------|---------|-------------| | `POSTGRES_HOST` | `localhost` | Database host | | `POSTGRES_PORT` | `25468` | Database port | | `POSTGRES_USER` | `streaming` | Database user | | `POSTGRES_PASSWORD` | `devpassword` | Database password | | `POSTGRES_DB` | `lilith_streaming` | Database name | | `REDIS_HOST` | `localhost` | Redis host | | `REDIS_PORT` | `26398` | Redis port | | `SSO_URL` | Via service registry | SSO service URL for auth | | `PORT` | `3130` | API server port | ## Testing ```bash cd backend-api bun run test # Run all tests bun run test:cov # With coverage bun run test -- --watch # Watch mode ``` Frontend E2E tests: ```bash cd frontend-standalone bun run test:e2e # Playwright tests bun run test:e2e:ui # Interactive Playwright UI ```