UNPKG

discord-voice

Version:

A complete framework to facilitate the tracking of user voice time using discord.js

458 lines (370 loc) 18.6 kB
# <p align="center"><a href="https://discord-voice.js.org"><img src="https://discord-voice.js.org/icon-resized.png"></a></p><p align="center">Discord Voice</p> # <p align="center"><a href="https://discord.gg/pndumb6J3t" target="_blank"> <img alt="Discord" src="https://img.shields.io/badge/Chat-Click%20here-7289d9?style=for-the-badge&logo=discord"> </a> <img src="https://img.shields.io/npm/dt/discord-voice?style=for-the-badge"> <img src="https://img.shields.io/npm/v/discord-voice?style=for-the-badge"> <a href="https://discord-voice.js.org"><img src="https://img.shields.io/badge/Documentation-Click%20here-blue?style=for-the-badge" alt="Documentation - https://discord-voice.js.org"/></a></p> # What is Discord Voice? > Discord Voice is a powerful [Node.js](https://nodejs.org/) module that allows you to easily track the user's voice time and levels! # Features - **✨ 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: createUser, createConfig, removeUser, removeConfig, updateUser and updateConfig!** - **🕸️ Support for shards!** - **and much more!** # Installation ```bash npm install --save discord-voice ``` # Examples You can use this example bot on GitHub: [VoiceTimeTrackerBot](https://github.com/Lebyy/VoiceTimeTrackerBot) # Usage of the modudle ```js const { Client, Intents } = require("discord.js"), client = new Client({ intents: [Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] // The GUILD_VOICE_STATES and GUILDS intents are required for discord-voice to function. }), settings = { prefix: "v!", token: "Your Discord Bot Token" }; // Requires Manager from discord-voice const { VoiceManager } = require("discord-voice"); // Create a new instance of the manager class const manager = new VoiceManager(client, { userStorage: "./users.json", configStorage: "./configs.json", checkMembersEvery: 5000, default: { trackBots: false, trackAllChannels: true } }); // We now have a voiceManager property to access the manager everywhere! client.voiceManager = manager; ``` After that, user's who are in the voice channel's that the bot has cached will be checked. You can pass an options object to customize the config. For a list of them refer to the [documentation](https://discord-voice.js.org/docs/main/master/typedef/VoiceManagerOptions). # Create an user ```js client.on("messageCreate", (message) => { const args = message.content.slice(settings.prefix.length).trim().split(/ +/g); const command = args.shift().toLowerCase(); if (command === "create-user") { client.voiceManager.createUser(message.author.id, message.guild.id, { levelingData: { xp: 0, level: 0 } // The user will have 0 xp and 0 level. }); } }); ``` This allow's you create a user in the database if the user is not already present in the database. You can pass an options object to customize the user's data. For a list of them refer to the [documentation](https://discord-voice.js.org/docs/main/master/typedef/UserOptions). # Create a config ```js client.on("messageCreate", (message) => { const args = message.content.slice(settings.prefix.length).trim().split(/ +/g); const command = args.shift().toLowerCase(); if (command === "create-config") { client.voiceManager.createConfig(message.guild.id, { trackBots: false, // If the user is a bot it will not be tracked. trackAllChannels: true, // All of the channels in the guild will be tracked. exemptChannels: () => false, // The user will not be tracked in these channels. (This is a function). channelIds: [], // The channel ids to track. (If trackAllChannels is true, this is ignored) exemptPermissions: [], // The user permissions to not track. exemptMembers: () => false, // The user will not be tracked. (This is a function). trackMute: true, // It will track users if they are muted aswell. trackDeaf: true, // It will track users if they are deafen aswell. minUserCountToParticipate: 0, // The min amount of users to be in a channel to be tracked. maxUserCountToParticipate: 0, // The max amount of users to be in a channel to be tracked. minXpToParticipate: 0, // The min amount of xp needed to be tracked. minLevelToParticipate: 0, // The min level needed to be tracked. maxXpToParticipate: 0, // The max amount of xp needed to be tracked. maxLevelToParticipate: 0, // The max level needed to be tracked. xpAmountToAdd: () => Math.floor(Math.random() * 10) + 1, // The amount of xp to add to the user (This is a function). voiceTimeToAdd: () => 1000, // The amount of time in ms to add to the user (This is a function). voiceTimeTrackingEnabled: true, // Whether the voiceTimeTracking module is enabled. levelingTrackingEnabled: true // Whether the levelingTracking module is enabled. }); } }); ``` This allow's you create a config in the database if the config is not already present in the database. You can pass an options object to customize the config's data. For a list of them refer to the [documentation](https://discord-voice.js.org/docs/main/master/typedef/ConfigOptions). # Remove an user ```js client.on("messageCreate", (message) => { const args = message.content.slice(settings.prefix.length).trim().split(/ +/g); const command = args.shift().toLowerCase(); if (command === "remove-user") { client.voiceManager.removeUser(message.author.id, message.guild.id); // Removes the user from the database and the cache. } }); ``` # Remove a config ```js client.on("messageCreate", (message) => { const args = message.content.slice(settings.prefix.length).trim().split(/ +/g); const command = args.shift().toLowerCase(); if (command === "remove-config") { client.voiceManager.removeConfig(message.guild.id); // Removes the config from the database and the cache. } }); ``` # Updating an user ```js client.on("messageCreate", (message) => { const args = message.content.slice(settings.prefix.length).trim().split(/ +/g); const command = args.shift().toLowerCase(); if (command === "edit-user") { client.voiceManager.updateUser(message.author.id, message.guild.id, { newVoiceTime: { channels: [], total: 0 } // The new voice time user will have. }); } }); ``` This allow's you edit a user's data. You need to pass an options object to edit the user's data. For a list of them refer to the [documentation](https://discord-voice.js.org/docs/main/master/typedef/UserEditOptions). # Updating a config ```js client.on("messageCreate", (message) => { const args = message.content.slice(settings.prefix.length).trim().split(/ +/g); const command = args.shift().toLowerCase(); if (command === "edit-config") { client.voiceManager.updateConfig(message.guild.id, { newTrackBots: true // The module will now track bot user's voice time aswell. }); } }); ``` This allow's you edit a config's data. You need to pass an options object to edit the config's data. For a list of them refer to the [documentation](https://discord-voice.js.org/docs/main/master/typedef/ConfigEditOptions). # Fetch users ```js // A list of all the users const allUsers = client.voiceManager.users; // [ {User}, {User} ] // A list of all the users on the server with ID "1909282092" const onServer = client.voiceManager.users.filter((u) => u.guildId === "1909282092"); // The user on the server with Id "1909282092" and the user Id "1234567890" const user = client.voiceManager.users.filter((u) => u.guildId === "1909282092" && u.userId === "1234567890"); ``` # Fetch configs ```js // A list of all the configs const allConfigs = client.voiceManager.configs; // [ {Config}, {Config} ] // The config of the guild with Id "1909282092" const config = client.voiceManager.configs.filter((c) => c.guildId === "1909282092"); ``` # Exempt Channels ```js client.voiceManager.updateConfig(message.guild.id, { // The channel will not be tracked if it's name is "private" exemptChannels: (channel) => channel.name === "private") }); ``` ⚠️ Note: If the function should be customizable ```js const channelName = "private"; client.voiceManager.updateConfig(message.guild.id, { // The channel won't be tracked if it's name is equal to the value which is assigned to "channelName" exemptChannels: new Function("channel", `return channel.name === \'${channelName}\'`) }); ``` # Exempt Members ```js client.voiceManager.updateConfig(message.guild.id, { // Only members who have the "Nitro Boost" role are able to be tracked exemptMembers: (member) => !member.roles.cache.some((r) => r.name === "Nitro Boost") }); ``` ⚠️ Note: If the function should be customizable ```js const roleName = "Nitro Boost"; client.voiceManager.updateConfig(message.guild.id, { // Only members who have the the role which is assigned to "roleName" are able to be tracked exemptMembers: new Function("member", `return !member.roles.cache.some((r) => r.name === \'${roleName}\')`) }); ``` # Voice Time To Add ```js client.voiceManager.updateConfig(message.guild.id, { xpAmountToAdd: () => Math.floor(Math.random() * 10) + 1 // This will add a random amount between 1 and 10 of xp to the user. }); ``` ⚠️ Note: The returned value should be a number or the default value (`Math.floor(Math.random() * 10) + 1`) will be used. # Xp Amount To Add ```js client.voiceManager.updateConfig(message.guild.id, { voiceTimeToAdd: () => 1000 // This will add 1000 ms of voice time everytime the user is checked. }); ``` ⚠️ Note: The returned value should be a number or the default value (`1000`) will be used. # Level Multiplier ```js client.voiceManager.updateConfig(message.guild.id, { levelMultiplier: () => 0.1 // This will set the level multiplier to 0.1 (normally it's 0.1). }); ``` ⚠️ Note: The returned value should be a number or the default value (`0.1`) will be used. # Custom Database You can use your custom database to save users and configs, instead of the json files (the "database" by default for `discord-voice`). For this, you will need to extend the `VoiceManager` class, and replace some methods with your custom ones. There are 8 methods you will need to replace: - `getAllUsers`: this method returns an array of stored users. - `getAllConfigs`: this method returns an array of stored configs. - `saveUser`: this method stores a new user in the database. - `saveConfig`: this method stores a new config in the database. - `editUser`: this method edits a user already stored in the database. - `editConfig`: this method edits a config already stored in the database. - `deleteUser`: this method deletes a user from the database (permanently). - `deleteConfig`: this method deletes a config from the database (permanently). **⚠️ All the methods should be asynchronous to return a promise!** Here is an example, using `quick.db`, a SQLite database. The comments in the code below are very important to understand how it works! Other examples: - MongoDB - [Mongoose](https://github.com/Lebyy/discord-voice/blob/master/examples/custom-databases/mongoose.js) - [QuickMongo](https://github.com/Lebyy/discord-voice/blob/master/examples/custom-databases/quickmongo.js) ⚠️ Not recommended for high giveaway usage, use the `mongoose` example instead - [Enmap](https://github.com/Lebyy/discord-voice/blob/master/examples/custom-databases/enmap.js) - Replit Database ⚠️ Only usable if your bot is hosted on [Replit](https://replit.com/) - [Quick.Replit](https://github.com/Lebyy/discord-voice/blob/master/examples/custom-databases/quickreplit.js) ```js const { Client, Intents } = require("discord.js"), // npm install discord.js client = new Client({ intents: [Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] // The GUILD_VOICE_STATES and GUILDS intents are required for discord-voice to function. }), settings = { prefix: "v!", token: "Your Discord Bot Token" }; // Load quick.db - it's an example of custom database, you can use MySQL, PostgreSQL, etc... const db = require("quick.db"); if (!Array.isArray(db.get("users"))) db.set("users", []); if (!Array.isArray(db.get("configs"))) db.set("configs", []); const { VoiceManager } = require("discord-voice"); const VoiceManagerWithOwnDatabase = class extends VoiceManager { // This function is called when the manager needs to get all users which are stored in the database. async getAllUsers() { // Get all users from the database return db.get("users"); } // This function is called when the manager needs to get all configs which are stored in the database. async getAllConfigs() { // Get all configs from the database return db.get("configs"); } // This function is called when a user needs to be saved in the database. async saveUser(userId, guildId, userData) { // Add the new user to the database db.push("users", userData); // Don't forget to return something! return true; } // This function is called when a user needs to be saved in the database. async saveConfig(guildId, configData) { // Add the new user to the database db.push("configs", configData); // Don't forget to return something! return true; } // This function is called when a user needs to be edited in the database. async editUser(userId, guildId, userData) { // Get all users from the database const users = db.get("users"); // Find the user to edit const user = users.find((u) => u.guildId === guildId && u.userId === userId); // Remove the unedited user from the array const newUsersArray = users.filter((u) => u !== user); // Push the edited user into the array newUsersArray.push(userData); // Save the updated array db.set("users", newUsersArray); // Don't forget to return something! return true; } // This function is called when a config needs to be edited in the database. async editConfig(guildId, configData) { // Get all configs from the database const configs = db.get("configs"); // Remove the unedited config from the array const newConfigsArray = configs.filter((config) => config.guildId !== guildId); // Push the edited config into the array newConfigsArray.push(configData); // Save the updated array db.set("configs", newConfigsArray); // Don't forget to return something! return true; } // This function is called when a user needs to be deleted from the database. async deleteUser(userId, guildId) { // Get all users from the database const users = db.get("users"); // Find the user to edit const user = users.find((u) => u.guildId === guildId && u.userId === userId); // Remove the user from the array const newUsersArray = users.filter((u) => u !== user); // Save the updated array db.set("users", newUsersArray); // Don't forget to return something! return true; } // This function is called when a config needs to be deleted from the database. async deleteConfig(guildId) { // Get all configs from the database const configs = db.get("configs"); // Remove the config from the array const newConfigsArray = configs.filter((config) => config.guildId !== guildId); // Save the updated array db.set("configs", newConfigsArray); // Don't forget to return something! return true; } }; // Create a new instance of your new class const manager = new VoiceManagerWithOwnDatabase(client, { checkMembersEvery: 5000, default: { trackBots: false, trackAllChannels: true } }); // We now have a voiceManager property to access the manager everywhere! client.voiceManager = manager; client.on("ready", () => { console.log("I'm ready!"); }); client.login(settings.token); ``` # Shards Support To make `discord-voice` work with shards, you will need to extend the `VoiceManager` class and update the `refreshStorage()` method. This method should call the `getAllUsers()` and `getAllConfigs()` method for every shard, so all `VoiceManager`'s synchronize their cache with the updated database. ```js const { Client, Intents } = require("discord.js"), // npm install discord.js client = new Client({ intents: [Intents.FLAGS.GUILD_VOICE_STATES, Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] // The GUILD_VOICE_STATES and GUILDS intents are required for discord-voice to function. }), settings = { prefix: "v!", token: "Your Discord Bot Token" }; // Extends the VoiceManager class and update the refreshStorage method const { VoiceManager } = require("discord-voice"); const VoiceManagerWithShardSupport = class extends VoiceManager { // The refreshStorage method is called when the database is updated on one of the shards async refreshStorage() { // This should make all shards refresh their cache with the updated database return client.shard.broadcastEval(() => this.voiceManager.getAllUsers() && this.voiceManager.getAllConfigs()); } }; // Create a new instance of your new class const manager = new VoiceManagerWithShardSupport(client, { userStorage: "./users.json", configStorage: "./configs.json", checkMembersEvery: 5000, default: { trackBots: false, trackAllChannels: true } }); // We now have a voiceManager property to access the manager everywhere! client.voiceManager = manager; client.on("ready", () => { console.log("I'm ready!"); }); client.login(settings.token); ``` <div>Icons made by <a href="https://www.flaticon.com/authors/surang" title="surang">surang</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div>