A TypeScript Discord bot (Node.js 20+) using discord.js.
/yeet minutes:<number> starts a timer, then disconnects all humans from all voice channels in the guild when it expires :>
- Slash commands:
/yeet,/yeets-incoming,/okay-dont-yeet - Required option:
minutes(integer) - Validation:
1to1440minutes (1 minute to 24 hours) - Uses Discord.js voice API:
member.voice.setChannel(null) - Permission checks:
- User must have Manage Channels
- Bot must have Move Members
- Responses:
- Components V2 container replies instead of embeds
- Ephemeral confirmation when a yeet is scheduled
- Ephemeral listing of active scheduled yeets in the current server without showing internal IDs
- Ephemeral interactive stop flow with a picker menu
- Public message when users are disconnected
- Activity status:
- Shows planned yeet count during the timer
- Resets to sponsor status after the yeet completes
- Node.js 20+
- TypeScript
- discord.js
- dotenv
- Docker (multi-stage image)
.
├── commands/
│ ├── list.ts
│ ├── stop.ts
│ └── yeet.ts
├── deploy-commands.ts
├── index.ts
├── lib/
│ └── yeet-manager.ts
│ └── yeet-ui.ts
├── Dockerfile
├── tsconfig.json
├── package.json
└── .env.example
- Install dependencies:
pnpm install- Create env file:
cp .env.example .env- Fill in
.envvalues:
BOT_TOKEN=your-bot-token
CLIENT_ID=your-application-client-id
GUILD_ID=your-dev-guild-id
GUILD_IDis optional. If set, commands deploy to that guild (fast updates). If omitted, commands deploy globally (can take longer to appear).
In the Discord Developer Portal:
- Enable Guilds and Guild Voice States intents for the bot.
- Invite the bot with permissions including:
- Move Members (required)
- Read/send permissions for the channel where command confirmations are posted
Users running /yeet must have Manage Channels in the server.
Build TypeScript:
pnpm buildDeploy slash commands:
pnpm deployStart bot:
pnpm startDev mode (no manual compile):
pnpm devHosted image:
docker pull iconical/voice-yeeter:latestRun hosted image:
docker run --rm --env-file .env iconical/voice-yeeter:latestBuild image:
docker build -t iconical/voice-yeeter:latest .Run container:
docker run --rm --env-file .env iconical/voice-yeeter:latestThe container entrypoint auto-runs slash command deployment before starting the bot. To skip deploy-on-start, set:
DEPLOY_COMMANDS_ON_START=falseExample file: docker-compose.example.yml
cp docker-compose.example.yml docker-compose.yml
docker compose up -d --builddocker buildx create --name multiarch --usedocker buildx inspect --bootstrapdocker buildx build \
--platform linux/amd64,linux/arm64 \
-t iconical/voice-yeeter:latest \
--push \
.buildx --load loads only one platform into local Docker (usually your host arch):
docker buildx build \
--platform linux/amd64 \
-t voice-yeeter:local \
--load \
.Run local loaded image:
docker run --rm --env-file .env voice-yeeter:local/yeet minutes:5- Immediately sends an ephemeral Components V2 confirmation.
- After 5 minutes, disconnects every non-bot member from voice channels in the guild.
- Posts a public summary message with the number of disconnected users.
/yeets-incoming- Shows all active yeets in the current server.
- Includes the target scope, planned disconnect count, and time remaining without exposing internal IDs.
/okay-dont-yeet- Shows the active yeets in the current server.
- Lets you pick one from a select menu to cancel it.
-
Command not showing up
- Re-run
pnpm deploy. - If global deploy is used (no
GUILD_ID), wait for propagation.
- Re-run
-
Bot cannot disconnect users
- Ensure bot has Move Members permission.
- Ensure bot role is high enough in role hierarchy.
-
No response to slash command
- Verify
BOT_TOKENandCLIENT_IDin.env. - Confirm bot is online and in the target server.
- Verify