beeta/chat-service/README.md

332 lines
7.4 KiB
Markdown
Raw Normal View History

2026-01-05 22:54:27 -05:00
# 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:**
```json
{
"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:**
```json
{
"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
```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
```bash
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
```bash
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:
```bash
docker-compose up -d chat-service
```
## Frontend Integration
### Basic Chat Panel
```svelte
<script>
import ChatPanel from '$lib/components/chat/ChatPanel.svelte';
export let realmId;
export let userColor = '#FFFFFF';
</script>
<ChatPanel {realmId} {userColor} />
```
### Pseudo-Terminal (~ key activation)
```svelte
<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:
```bash
curl http://localhost:8081/api/chat/admin/settings
```
View logs:
```bash
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