Goal: build a Discord bot that does the normal bot things people actually use — 🎧 music controls, 🧰 slash commands, and (optionally) 🤖 a local AI “/ask” command powered by LM Studio.
This isn’t “AI sci-fi”. This is a practical automation project: your PC does the boring parts, and Discord gets a bot that feels responsive and useful.
Rule I use: ⏱️ If the bot can’t respond in 10 seconds (or show it’s working), it doesn’t work.
✅ What this bot can do (v1)
- Music:
/join,/play,/pause,/resume,/skip,/queue,/leave🎵 - Utility:
/ping,/help,/roll🧰 - Optional:
/ask→ routes to LM Studio running locally 🤖
The vibe: a bot that feels “premium” because it’s reliable — no mystery silence, no broken replies, no random crashes after one song.
🧠 The simple architecture
Discord (slash command)
└─> Your bot (Node)
├─> Voice engine (@discordjs/voice + FFmpeg) 🎧
└─> Optional AI engine (LM Studio /v1) 🤖
If you’re new: don’t panic. You’re basically building a small server app that listens for Discord commands and runs two jobs:
play audio, and (optionally) call a local text model.
🔗 The 3 links you actually need
- discord.js Guide (slash commands + bot structure): https://discordjs.guide/
- Voice guide (audio player lifecycle + resources): https://discordjs.guide/voice/
- LM Studio OpenAI-compatible API (local /v1): https://lmstudio.ai/docs/developer/openai-compat
🎛 Step 1 — Create the Discord bot
- Go to the Discord Developer Portal → create an application.
- Add a bot user.
- Copy the bot token (keep it private).
- Invite it to your server with scopes:
bot+applications.commands. - Give it permissions: Send Messages, Use Slash Commands, Connect, Speak.
Tip: Slash commands are cleaner than “message commands” because you don’t need to enable message content intents just to get started.
🤖 Step 2 (optional) — Turn your PC into the bot’s “brain” with LM Studio
LM Studio can run a model locally and expose an OpenAI-compatible endpoint. That means your bot can send a normal chat completion request to:
http://127.0.0.1:1234/v1/chat/completions
Why this matters: you’re not waiting on a cloud service, you’re not juggling accounts, and you control the model + the machine.
Receipt: when this works, you can type /ask in Discord and the reply comes from your own PC.
🎧 Step 3 — Music playback without pain
Here’s the beginner truth: the “music bot” part is mostly about managing a queue and handling the player lifecycle properly.
✅ The core pattern (what makes it reliable)
- One queue per server (guild)
- One audio player per server
- A playNext() function that always knows what to do next
- When the player goes Idle, call playNext() again
If you miss the Idle handler, you get the classic failure: “it played one thing and stopped.”
Rule: If your bot can’t play the next track automatically, it’s not a music bot — it’s a demo.
⚠️ The music source gotcha (start stable)
If you want your first version to actually work, use sources that don’t constantly break:
- ✅ direct MP3/OGG stream URLs (internet radio)
- ✅ your own hosted audio files
- ✅ local files you control
Save the “hard mode” sources for later. The goal is a bot that works every day, not a bot that works once.
🪲 Gotchas and fixes (the ones that waste hours)
1) “Interaction failed”
Cause: Discord expects a response quickly. If your command takes time, you must acknowledge it first.
Fix: defer the reply immediately, then edit the reply when you finish. (This is standard slash command behaviour.)
2) Bot joins voice but plays silence 🔇
Cause: missing Opus or FFmpeg, or the audio resource isn’t built correctly.
Fix: follow the discord.js voice setup and verify dependencies using their voice guide.
3) Plays first track then stops
Cause: no “Idle → playNext()” loop.
Fix: wire the player status events so the queue keeps moving.
4) /play given a webpage URL
Cause: a webpage is not an audio stream.
Fix: start with direct streams, then upgrade later.
🧾 The “Receipts” checklist (so you know it’s real)
Record a quick screen capture and prove it:
/join→ bot joins voice 🎧/playa direct audio stream → audio plays ✅/queue→ shows queue state 🧾- (optional)
/ask→ bot replies from LM Studio 🤖
That’s the moment where it stops being “AI hype” and starts being your machine doing useful work.
🚀 Next upgrades (if you want it to feel premium)
- 🔐 Role-based command locking (mods only for skip/clear queue)
- 🧠 Short memory for /ask (last 6–10 messages)
- 📌 “Now playing” embed + progress
- 🧰 Tool-style AI: the model can request “show queue”, “now playing”, etc. (LM Studio supports tool calling)
If you want, I’ll publish a “v2” post that includes the full ready-to-run project structure, command registration, and the exact code you can copy into a folder and run.