A Discord music bot for Stage channels. Submit Suno, YouTube, or Spotify links from any text channel and the bot plays them in order in the voice/stage channel you're currently in.
| Command | Description |
|---|---|
/submit <url> |
Add a Suno, YouTube, or Spotify link to the queue |
/queue |
Show what's coming up |
/nowplaying |
Show the current track |
/history |
Recently played tracks |
/play |
Resume playback if paused |
/skip |
Skip the current track (admin) |
/stop |
Stop, clear queue, disconnect (admin) |
/shuffle |
Shuffle the upcoming queue (admin) |
Admin = members with Manage Channels or Manage Server permission, or
any user listed in ADMIN_USER_IDS.
- Suno (
suno.com/song/<id>) — scrapes the public Open Graph metadata to find the mp3 stream URL. SetSUNO_COOKIEonly if you want to play private or unlisted songs. - YouTube (
youtube.com/watch?v=…,youtu.be/…, Shorts, Music) — streamed via@distube/ytdl-core. - Spotify (
open.spotify.com/track/<id>) — Spotify itself does not allow third-party audio streaming, so the bot looks up the track's title/artist viaspotify-url-infoand then plays the closest YouTube match.
Playlists and albums are not supported — submit individual tracks.
- Install Node.js 20+, then
npm install. - Create a Discord application at https://discord.com/developers/applications:
- Copy the Bot Token and Application Client ID into
.env - Invite the bot with scopes
bot+applications.commandsand at minimum the Connect, Speak, and Use Slash Commands permissions. - For Stage channels, the bot also needs Request to Speak, and ideally Mute Members so it can promote itself to speaker automatically.
- Copy the Bot Token and Application Client ID into
cp .env.example .envand fill inDISCORD_TOKENandDISCORD_CLIENT_ID. SetDISCORD_GUILD_IDwhile developing so command updates appear instantly in one server; leave it blank for global registration.npm run deployonce to register slash commands.npm run dev(watch mode) ornpm run build && npm start(production).
Use the OAuth2 URL Generator in the developer portal. Required scopes:
bot and applications.commands. Recommended permissions:
Connect, Speak, Send Messages, Embed Links,
Use Application Commands, Request to Speak, and Mute Members
(the last lets the bot auto-promote itself to speaker on Stage channels).
docker build -t suno-discord-bot .
docker run --rm --env-file .env --name suno-bot suno-discord-botThe image is multi-stage: deps + TypeScript compile in the builder, then a
slim runtime layer with prod deps only. Set DISCORD_TOKEN, DISCORD_CLIENT_ID,
and (optionally) DISCORD_GUILD_ID / ADMIN_USER_IDS / SUNO_COOKIE via
--env-file or -e flags. Run npm run deploy once locally before starting
the container so slash commands are registered.
When a user runs /submit while in a Stage channel, the bot joins as audience
and then tries to:
setSuppressed(false)— works if the bot has Mute Members or is a stage moderator.- Otherwise
setRequestToSpeak(true)— a moderator must approve it.
If you see the bot connected but silent on a Stage, make it a moderator or grant Mute Members.
- Suno, YouTube, and Spotify can change their endpoints/anti-bot at any time. If one source stops working, check that source's library is up to date.
- Queue state lives in memory; restarting the bot clears everything.
- Per-guild — different servers have independent queues and history.