Files
joel/README.md
2026-03-22 02:35:10 +01:00

136 lines
4.3 KiB
Markdown

# Joel Discord Bot
A Discord bot with AI-powered responses and message tracking.
## Quick Start
```bash
# Install dependencies
bun install
# Set environment variables
cp .env.example .env
# Edit .env with your tokens
# Run in development mode
bun run dev
# Run in production
bun run start
```
## Project Structure
See [src/README.md](src/README.md) for detailed architecture documentation.
```
src/
├── core/ # Bot client, config, logging
├── commands/ # Slash commands
├── events/ # Discord event handlers
├── features/ # Feature modules (Joel AI, message logging)
├── services/ # External services (AI providers)
├── database/ # Database schema and repositories
└── utils/ # Shared utilities
```
## Environment Variables
| Variable | Description |
| ----------------------- | --------------------------------------- |
| `DISCORD_TOKEN` | Discord bot token |
| `DISCORD_CLIENT_ID` | Discord application client ID |
| `DISCORD_CLIENT_SECRET` | Discord application client secret |
| `OPENROUTER_API_KEY` | OpenRouter API key for AI |
| `AI_CLASSIFICATION_FALLBACK_MODELS` | Comma-separated fallback model IDs for classification requests |
| `KLIPY_API_KEY` | Klipy API key for GIF search (optional) |
| `ELEVENLABS_API_KEY` | ElevenLabs API key for voiceover |
| `ELEVENLABS_VOICE_ID` | Default ElevenLabs voice ID (optional) |
| `ELEVENLABS_MODEL` | ElevenLabs model ID (default: `eleven_multilingual_v2`) |
| `DATABASE_PATH` | SQLite file path (default: `./data/db.sqlite3`) |
| `WEB_PORT` | Port for web dashboard (default: 3000) |
| `WEB_BASE_URL` | Base URL for web dashboard |
| `SESSION_SECRET` | Secret for session encryption |
## Data Persistence
- Bot options and other runtime state are stored in SQLite.
- Keep `DATABASE_PATH` on persistent storage so updates/redeploys do not reset settings.
- Backward compatibility: if `DATABASE_PATH` is unset and `src/database/db.sqlite3` exists, it is used automatically.
- Recommended one-time migration:
```bash
mkdir -p data && cp src/database/db.sqlite3 data/db.sqlite3
```
- Docker example:
```bash
docker run -d \
--name joel-discord \
-v joel_data:/data \
--env-file .env \
your-image:latest
```
## Docker
Build the image:
```bash
docker build -t ghcr.io/your-org/joel-bot:latest .
```
Run it locally:
```bash
docker run -d \
--name joel-bot \
-p 3000:3000 \
-v joel_data:/data \
--env-file .env \
ghcr.io/your-org/joel-bot:latest
```
The container now starts in production mode and does not enable the CSS file watcher.
## k3s
The repo includes starter manifests in [`k8s/deployment.yaml`](/Users/eric/Projects/joel-discord/k8s/deployment.yaml), [`k8s/secret.example.yaml`](/Users/eric/Projects/joel-discord/k8s/secret.example.yaml), and [`k8s/ingress.example.yaml`](/Users/eric/Projects/joel-discord/k8s/ingress.example.yaml).
Typical flow:
```bash
# Build and push the image
docker build -t ghcr.io/your-org/joel-bot:latest .
docker push ghcr.io/your-org/joel-bot:latest
# Create your secret manifest from the example and fill in real values
cp k8s/secret.example.yaml k8s/secret.yaml
# Apply namespace, PVC, deployment, and service
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/secret.yaml
# Optional if you want the web UI exposed through Traefik
kubectl apply -f k8s/ingress.example.yaml
```
Notes:
- Update the image in `k8s/deployment.yaml` to your registry path.
- Set `WEB_BASE_URL` in the secret to the public HTTPS URL you expose through ingress.
- The deployment mounts `/data` on a PVC and stores SQLite at `/data/db.sqlite3`.
- k3s usually provisions the PVC automatically via the default `local-path` storage class.
## Scripts
| Script | Description |
| --------------------- | --------------------------- |
| `bun run dev` | Development with hot reload |
| `bun run start` | Production start |
| `bun run build` | Build for production |
| `bun run db:generate` | Generate DB migrations |
| `bun run db:migrate` | Run DB migrations |
| `bun run db:studio` | Open Drizzle Studio |
| `bun run typecheck` | Type check without emit |