beeta/chat-service/README.md
2026-01-05 22:54:27 -05:00

7.4 KiB

Chat Service for realms.india

A scalable, real-time chat service built with Drogon C++ framework and Redis for the realms.india streaming platform.

Features

  • Real-time WebSocket Communication - Instant message delivery
  • Guest Chat Support - Anonymous users with configurable naming patterns
  • Redis-Based Storage - Fast, in-memory message storage with configurable retention
  • Moderation Tools - Ban, mute, timeout, and message deletion
  • Slow Mode - Per-realm rate limiting
  • Links Filtering - Configurable link permission per realm
  • Global/Local Channels - Multi-channel support
  • User Color Preservation - Registered users maintain their platform colors
  • Auto-cleanup - Periodic message cleanup based on retention settings

Architecture

Components

  1. Chat Service (Port 8081) - Drogon-based C++ backend

    • WebSocket server for real-time communication
    • REST API for settings and moderation
    • Redis integration for message storage
  2. Redis Database 1 - Message and moderation data

    • Messages (sorted sets per realm)
    • Ban/mute lists
    • Chat settings
    • Slow mode tracking
  3. PostgreSQL - Persistent settings

    • Realm chat configurations
    • Chat moderators
    • Global chat settings

Data Flow

Frontend (SvelteKit)
    ↓ WebSocket
OpenResty (Proxy)
    ↓ /chat/*
Chat Service (Drogon)
    ↓
Redis (Messages) + PostgreSQL (Settings)

API Endpoints

WebSocket

Connect: ws://host/chat/stream/{realmId}?token=<jwt>

Client → Server Messages:

{
  "type": "message",
  "content": "Hello world!",
  "userColor": "#FF5733"
}

{
  "type": "join",
  "realmId": "realm-uuid"
}

{
  "type": "mod_action",
  "action": "ban|mute|timeout|delete",
  "targetUserId": "user-uuid",
  "messageId": "message-uuid",
  "duration": 300,
  "reason": "Spam"
}

Server → Client Messages:

{
  "type": "welcome",
  "username": "guest1234",
  "userId": "guest:guest1234",
  "isGuest": true,
  "isModerator": false,
  "realmId": "realm-uuid"
}

{
  "type": "history",
  "messages": [...]
}

{
  "type": "new_message",
  "messageId": "uuid",
  "username": "user",
  "content": "Hello!",
  ...
}

{
  "type": "message_deleted",
  "messageId": "uuid"
}

{
  "type": "error",
  "error": "You are muted"
}

REST API

Messages

  • GET /api/chat/messages/:realmId?limit=100&before=<timestamp> - Get messages
  • POST /api/chat/send - Send message (alternative to WebSocket)
  • DELETE /api/chat/message/:messageId?realmId=<id> - Delete message

Settings

  • GET /api/chat/settings/:realmId - Get realm chat settings
  • PUT /api/chat/settings/:realmId - Update realm settings (moderator only)

Moderation

  • POST /api/chat/ban - Ban user from realm
  • POST /api/chat/unban - Unban user
  • POST /api/chat/mute - Mute user (temporary)
  • POST /api/chat/unmute - Unmute user
  • POST /api/chat/timeout - Timeout user (short-term mute)
  • GET /api/chat/banned/:realmId - List banned users

Admin

  • GET /api/chat/admin/settings - Get global settings
  • PUT /api/chat/admin/settings - Update global settings
  • GET /api/chat/admin/stats - Get chat statistics

Configuration

chat-service/config.json

{
  "redis": {
    "host": "redis",
    "port": 6379,
    "db": 1
  },
  "chat": {
    "default_retention_hours": 24,
    "max_message_length": 500,
    "max_messages_per_realm": 1000,
    "guest_prefix": "guest",
    "guest_id_pattern": "{prefix}{number}",
    "cleanup_interval_seconds": 300
  }
}

Guest ID Patterns

Customize guest usernames with placeholders:

  • {prefix} - Guest prefix (configurable)
  • {number} - Auto-incrementing number
  • {random} - Random 4-digit hex

Examples:

  • {prefix}{number} → guest1, guest2, guest3...
  • anon{random} → anon4a7f, anonb2c9...
  • friend_{number} → friend_1, friend_2...

Realm Settings

Customize chat behavior per realm (stored in PostgreSQL realms table):

  • chat_retention_hours (default: 24) - How long to keep messages
  • chat_slow_mode_seconds (default: 0) - Minimum seconds between messages
  • chat_links_allowed (default: true) - Allow URLs in messages
  • chat_subscribers_only (default: false) - Restrict chat to subscribers

Moderation

Moderators

  • Realm creators are auto-moderators
  • Admins are moderators everywhere
  • Additional moderators stored in chat_moderators table

Actions

  1. Ban - Permanent, prevents all messages
  2. Mute - Temporary silence (duration in seconds)
  3. Timeout - Short-term mute (typically 60s)
  4. Delete Message - Remove specific message

Redis Schema

# Messages (sorted set, score = timestamp)
chat:messages:{realmId} → [{message JSON}, ...]

# Global settings
chat:settings:global → {guestPrefix, guestIdPattern, defaultRetentionHours}

# Realm settings
chat:settings:realm:{realmId} → {retentionHours, slowModeSeconds, ...}

# Bans (set)
chat:banned:{realmId} → {userId1, userId2, ...}

# Mutes (string with TTL)
chat:muted:{realmId}:{userId} → "1"

# Slow mode tracking (string with TTL)
chat:slowmode:{realmId}:{userId} → "1"

# Active users (sorted set, score = last seen)
chat:active:{realmId} → {userId: timestamp}

# Guest counter
chat:guest:counter → integer

Building

Prerequisites

  • CMake 3.15+
  • C++20 compiler (GCC 10+ or Clang 12+)
  • Conan package manager
  • Docker (for containerized build)

Local Build

cd chat-service

# Install dependencies
conan install . --output-folder=build --build=missing -s compiler.cppstd=20

# Build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build . -j$(nproc)

# Run
./bin/chat_service

Docker Build

cd chat-service
docker build -t chat-service .
docker run -p 8081:8081 \
  -e JWT_SECRET=your-secret \
  -e REDIS_HOST=redis \
  chat-service

Deployment

The chat service is automatically included in the main docker-compose.yml:

docker-compose up -d chat-service

Frontend Integration

Basic Chat Panel

<script>
  import ChatPanel from '$lib/components/chat/ChatPanel.svelte';
  export let realmId;
  export let userColor = '#FFFFFF';
</script>

<ChatPanel {realmId} {userColor} />

Pseudo-Terminal (~ key activation)

<script>
  import ChatTerminal from '$lib/components/chat/ChatTerminal.svelte';
</script>

<ChatTerminal defaultRealmId="realm-uuid" />

Add to your root layout to make it globally available.

Security

  • JWT Authentication - Required for registered users
  • Rate Limiting - 20 messages/second per IP at proxy level
  • Content Validation - Length limits, XSS prevention
  • Moderator Checks - Permission validation for all mod actions
  • CORS - Restricted to localhost origins in development

Performance

  • WebSocket - Persistent connections, minimal overhead
  • Redis - Sub-millisecond message retrieval
  • Auto-cleanup - Configurable retention to manage memory
  • Message Cap - Max 1000 messages per realm (configurable)

Monitoring

Check service health:

curl http://localhost:8081/api/chat/admin/settings

View logs:

docker logs realms-chat-service

Future Enhancements

  • Emoji support
  • Message reactions
  • Thread/reply support
  • User mentions (@username)
  • Rich media embeds
  • Chat commands (/me, /shrug, etc.)
  • Message search
  • Whispers/DMs
  • Channel creation (beyond realms)
  • Chatbot integration hooks