DEV Community

lavvor
lavvor

Posted on

I Built a Zero-Dependency Discord.js Package That Creates Temporary Voice Channels Automatically

I Built a Zero-Dependency Discord.js Package That Creates Temporary Voice Channels Automatically

The Problem Every Discord Bot Developer Faces

You run a gaming server or a community Discord. You want a "Join to Create" feature – users join a specific voice channel, and the bot instantly spawns a private channel for them. When they leave, the channel disappears.

I've written this logic at least 10 times. Every time, the same pain points:

  • Handling Discord's rate limits when multiple users join at once
  • Recovering channel-owner mappings after bot crashes
  • Transferring ownership when the creator leaves
  • Deleting empty channels without leaving orphans

I decided to stop copying code between projects and build a proper npm package.

What I Built

discord-dynamic-voice is a zero-dependency, TypeScript-first manager for Discord.js v14 bots. It handles the full lifecycle of dynamic voice channels.

How it works:

  1. User joins your designated "creator" channel
  2. Package creates a new voice channel with cloned permissions
  3. User is moved automatically into their new channel
  4. Local JSON file stores channelId -> creatorId for crash recovery
  5. When empty, channel self-destructs

Key features:

  • Rate-limit safe request queue (prevents Discord 429 errors)
  • Automatic owner handover if the creator leaves
  • Spam prevention cooldowns per user
  • Full TypeScript support with type definitions
  • Event hooks: channelCreated, channelEmpty, ownerSwapped, error
  • Slash command handlers: rename, limit, lock, unlock

Why This Matters

Most Discord bot developers rewrite the same voiceStateUpdate snippet for every project. Those snippets break with every Discord API update.

This package is actively maintained, versioned, and tested across Node.js 18, 20, and 22.

Installation

npm install discord-dynamic-voice
npm install discord.js@^14.0.0

Basic Usage

const { Client, GatewayIntentBits } = require('discord.js');
const { DynamicVoiceManager } = require('discord-dynamic-voice');

const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates
]
});

const voiceManager = new DynamicVoiceManager(client, {
creatorChannelId: '123456789012345678',
defaultName: "{username}'s space",
autoDeleteWhenEmpty: true
});

voiceManager.on('channelCreated', (channel, creator) => {
console.log(${creator.tag} created ${channel.name});
});

client.on('ready', async () => {
await voiceManager.init();
console.log(Bot ready);
});

client.login('YOUR_TOKEN');

Slash Commands

const { handleRename, handleLimit, handleLock, handleUnlock } = require('discord-dynamic-voice');

if (commandName === 'rename') {
await handleRename(voiceManager, interaction, channel, interaction.member);
}

Crash Recovery

If your bot restarts while dynamic channels are active, the package:

  1. Reads the local JSON state file
  2. Checks which channels still exist
  3. Re-associates them with their owners
  4. Deletes any truly orphaned channels

No more ghost channels cluttering your server.

Links

npm: https://www.npmjs.com/package/discord-dynamic-voice
GitHub: https://github.com/Lavvordev/discord-dynamic-voice

Try it out. Star the repo. Stop rewriting voiceStateUpdate.

Top comments (0)