Discord Voice is a powerful Node.js module that allows you to easily track the user's voice time and levels!
- ✨ Easy to use!
- 📁 Support for all databases! (default is json)
- ⚙️ Very customizable! (ignored channels, ignored members, ignored permissions, xp amount to add, voice time to add etc...)
- 🚀 Super powerful: create, edit and delete!
- 🕸️ Support for shards!
- 🔐 Discord.js Collection Based!
- and much more!
npm install --save discord-voice
You can use this example bot on GitHub: VoiceTimeTrackerBot
Required Discord Intents: Guilds
and GuildVoiceStates
.
const Discord = require('discord.js');
const client = new Discord.Client({
intents: [
Discord.IntentsBitField.Flags.Guilds,
Discord.IntentsBitField.Flags.GuildVoiceStates
]
});
// Requires Manager from discord-voice
const { VoiceTimeManager } = require('discord-voice');
const manager = new VoiceTimeManager(client, {
storage: './guilds.json',
default: {
trackBots: false,
trackAllChannels: true
}
});
// We now have a voiceTimeManager property to access the manager everywhere!
client.voiceTimeManager = manager;
client.on('ready', () => {
console.log('Bot is ready!');
});
client.login(process.env.DISCORD_BOT_TOKEN);
After that, users who are in the voice channels that the bot has cached will be checked. You can pass an options object to customize the giveaways. Here is a list of them:
- client: the discord client (your discord bot instance).
- and many other optional parameters to customize the manager - read documentation
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'create-guild') {
const guildId = interaction.options.getString('guildId');
const users = interaction.options.getString('users');
const options = interaction.options.getString('options');
client.voiceTimeManager.create(guildId, users, options).then(() => {
interaction.reply('Success! Guild Created!');
}).catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
};
});
- This allow's you create a guild in the database if the guild is not already present in the database. You can pass an options object to customize the guild's data. For a list of them refer to the documentation.
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'edit') {
const guildId = interaction.options.getString('guildId');
client.voiceTimeManager.edit(guildId, {
trackBots: true,
trackAllChannels: false
}).then(() => {
interaction.reply('Success! Guild updated!');
}).catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
- This allow's you edit a guild's data. You need to pass an options object to edit the guild's data. For a list of them refer to the documentation.
client.on('interactionCreate', (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === 'delete') {
const guildId = interaction.options.getString('guildId');
client.voiceTimeManager.delete(guildId).then(() => {
interaction.reply('Success! Guild deleted!');
}).catch((err) => {
interaction.reply(`An error has occurred, please check and try again.\n\`${err}\``);
});
}
});
- This allow's you delete a guild from the database if the guild is present in the database.
// A list of all the guilds in the database.
const allGuilds = client.voiceTimeManager.guilds; // Returns a Discord Collection of Guilds (Discord.Collection<guildId, guildData>)
// Returns the guild with Id "1909282092"
const guild = client.voiceTimeManager.guilds.get('1909282092'); // Returns a Guild. (Discord.Collection<guildId, guildData>)
// A list of all guilds with atleast 1 user in the database.
const guildWithUsers = client.voiceTimeManager.guilds.filter((guild) => guild.users.size > 0); // Returns a Discord Collection of Guilds (Discord.Collection<guildId, guildData>)
const guildId = '1909282092';
const guild = client.voiceTimeManager.guilds.get(guildId);
guild.config.edit({
// The channel will not be tracked if it's name is "private"
exemptChannels: (channel) => channel.name === "private")
});
guild.extraData
, you can use the Function constructor:
const guildId = '1909282092';
const guild = client.voiceTimeManager.guilds.get(guildId);
const channelName = "private";
guild.config.edit({
// The channel won't be tracked if it's name is equal to the value which is assigned to "channelName"
exemptChannels: new Function(
"channel",
"guild",
`return channel.name === \'${channelName}\'`)
});
⚠ Note
- You can use
this
, instead of theguild
parameter, inside of the function string to access anything of the giveaway instance.
For example:this.extraData
, orthis.client
. - Strings have to be "stringified" (wrapped in quotation marks) again like you can see in the example.
Array brackets also have to be stated again. - Global variables which contain numbers with more than 16 digits cannot be used.
=> Snoflakes have to be "stringified" correctly to avoid misbehaviour. - If you want to make an asynchronous function in this format, refer to this article.
- Because of those various complications it is therefore highly suggested to use
guild.extraData
for storing variables.
But if you really want to do it in this way and need more information/help, please visit the Discord Server.
const guildId = '1909282092';
const guild = client.voiceTimeManager.guilds.get(guildId);
guild.config.edit({
// Only members who have the "Nitro Boost" role are able to be tracked
exemptMembers: (member) => !member.roles.cache.some((r) => r.name === "Nitro Boost")
});
guild.extraData
, you can use the Function constructor:
const guildId = '1909282092';
const guild = client.voiceTimeManager.guilds.get(guildId);
const roleName = "Nitro Boost";
guild.config.edit({
// Only members who have the the role which is assigned to "roleName" are able to be tracked
exemptMembers: new Function(
"member",
"guild",
`return !member.roles.cache.some((r) => r.name === \'${roleName}\')`)
});
⚠ Note
- You can use
this
, instead of theguild
parameter, inside of the function string to access anything of the giveaway instance.
For example:this.extraData
, orthis.client
. - Strings have to be "stringified" (wrapped in quotation marks) again like you can see in the example.
Array brackets also have to be stated again. - Global variables which contain numbers with more than 16 digits cannot be used.
=> Snoflakes have to be "stringified" correctly to avoid misbehaviour. - If you want to make an asynchronous function in this format, refer to this article.
- Because of those various complications it is therefore highly suggested to use
guild.extraData
for storing variables.
But if you really want to do it in this way and need more information/help, please visit the Discord Server.
const guildId = '1909282092';
const guild = client.voiceTimeManager.guilds.get(guildId);
guild.config.edit({
xpAmountToAdd: (guild) => Math.floor(Math.random() * 10) 1 // This will add a random amount between 1 and 10 of xp to the user.
});
Math.floor(Math.random() * 10) 1
) will be used.
const guildId = '1909282092';
const guild = client.voiceTimeManager.guilds.get(guildId);
guild.config.edit({
voiceTimeToAdd: () => 1000 // This will add 1000 ms of voice time everytime the user is checked.
});
1000
) will be used.
const guildId = '1909282092';
const guild = client.voiceTimeManager.guilds.get(guildId);
guild.config.edit({
levelMultiplier: () => 0.1 // This will set the level multiplier to 0.1 (normally it's 0.1).
});
0.1
) will be used.
You can use your custom database to save guilds, instead of the json files (the "database" by default for discord-voice
). For this, you will need to extend the VoiceTimeManager
class, and replace some methods with your custom ones. There are 4 methods you will need to replace:
getAllGuilds
: this method returns an array of stored guilds.saveGuild
: this method stores a new guild in the database.editGuild
: this method edits a guild already stored in the database.deleteGuild
: this method deletes a guild from the database (permanently).
SQL examples
NoSQL examples
- MongoDB
- Mongoose
- QuickMongo
⚠️ Not recommended for high giveaway usage, use themongoose
example instead
- Apache CouchDB - Nano
- Replit Database
⚠️ Only usable if your bot is hosted on Replit