A self-hosted Discord bot built with discord.js: music playback (YouTube/Spotify), reminders, quote commands, and an optional local AI assistant (text chat + voice) backed by your own OpenAI-compatible endpoints.
npm install
cp .env.example .env # add your Discord token; everything else is optionalnpx tsx src/index.ts # development
./deploy.sh # production (Docker): git pull + rebuild + restart- Music:
/play·/skip·/stop·/queue·/music - AI assistant:
/ask·/listen·/leave(voice, wake word "Jarvis") — or @mention the bot to chat - Utility:
/remind·/reminders·/timezone·/voicelog·/help - Quotes: auto-generated from
data/quotes/*.json(e.g./8ball) - Admin:
/status— requires your user ID inADMIN_IDS
Commands are not deployed on startup. After adding or changing a command:
npx tsx scripts/deploy-commands.ts
# or in Docker:
docker compose exec -T sonus npx tsx scripts/deploy-commands.tsnpx tsx scripts/clear-commands.ts removes all registered commands.
Chat (@mention), /ask, and voice (/listen) use self-hosted OpenAI-compatible services: an LLM (OLLAMA_API_URL), Whisper STT (WHISPER_URL), TTS (TTS_URL), and SearXNG web search (SEARXNG_URL). See .env.example. AI features stay disabled until configured.
For age-restricted videos and higher rate limits, export your YouTube cookies to data/cookies.txt (e.g. with a cookies.txt browser extension). Auto-detected on startup.
- Track links work out of the box (converted to a YouTube search via idonthavespotify).
- Playlists (used as background playlists) need Spotify API credentials: set them in
.env(see.env.example), then runnpx tsx scripts/spotify-auth.ts.
A live dashboard (http://<host>:3000/) and JSON API are served on HEALTH_PORT (default 3000): GET /api/status, GET /api/guilds[/:id], an SSE stream at /api/events, and POST endpoints for feature toggles and music controls. There is no auth — keep the port LAN-only.