/fanfare, which joins the voice channel of the person who asks and plays a sound, then /hush, which stops it. On the way, it explains why some files play as they are and others need a tool, and what Discord encrypts.
A sound in public/
Sounds are files, like the images your bot sends: they go inpublic/. Put one there, public/sounds/fanfare.ogg. Any short sound will do; the next section says which formats work.
The command
Createsrc/commands/fanfare.ts:
src/commands/fanfare.ts
join() in your files and asked for it. Join a voice channel of your test server, type /fanfare: the bot comes in, plays the sound, and leaves.
Read the command again, line by line:
member.voiceChannelis the channel the person is in, ornull. The answer comes first: a command has 3 seconds to answer, and joining takes a moment.channel.join()resolves once the bot is in and can play. Joining the channel it is already in changes nothing.voice.play(...)resolves when the sound has been played, soleave()comes after it.
Why Opus
Discord only carries one format in voice: Opus, made for voices and music over the internet. A file that is already Opus (.ogg, .opus, and the .webm of most videos) is sent as it is, costing nothing. Anything else (.mp3, .wav, a link to a radio) must be converted while it plays, and that is the job of ffmpeg, a free tool you install on the machine of the bot. ChapterJS finds it by itself; when it is missing, the error says so and what to do:
.ogg: then nothing is needed where the bot runs.
Stopping it
guild.voice is the bot in voice in a server, or null. Create src/commands/hush.ts:
src/commands/hush.ts
stop() ends the sound: the play() of /fanfare resolves at once, and the bot leaves. pause() and resume() work the same way.
What Discord encrypts
What is said in a voice channel is end-to-end encrypted: only the people in the channel can hear it, not even Discord’s servers. Every app that speaks there must take part, bots included. Your bot does it with libdave, the library Discord’s own apps use, which comes with ChapterJS: nothing to install, nothing to write. One consequence: while your bot is alone in a channel, there is nobody to encrypt for, so what it plays is not sent. As soon as someone is there, they hear it.Points of attention
- Answer first, then join. A command has 3 seconds to answer; joining and playing take longer.
- Permissions. The bot needs Connect and Speak in the channel. Without them, the error names the one that is missing.
- One connection per server.
join()on another channel of the same server moves the bot there; a server can’t have the bot in two voice channels. - The intent comes from your files.
GUILD_VOICE_STATESis asked when a file callsjoin(). It is not privileged: no switch in the Developer Portal.
Recap
- Sounds go in
public/;asset()names them. member.voiceChannel→channel.join()→voice.play()→voice.leave().- Opus files play as they are; anything else needs ffmpeg on the machine of the bot.
guild.voiceis the bot in voice in a server:stop(),pause(),resume().- Voice is end-to-end encrypted, and ChapterJS does it for you.
Buttons
Put a button under a message, and run code when it is clicked.
Guide: Playing in voice
Joining, playing and leaving, in short.