Advanced all-in-one discord bot with prefix & slash commands
MIT License
To test out Testify, be sure to invite him to your server by clicking here
Project Setup
Fork the Github project :
Click the Code
button. From the drop-down that appears, click Download ZIP
to download the entire repository as a ZIP folder.
Extract the files to a new folder and open it with Visual Studio Code.
Obtain Discord Bot Token
Sign in to Discord Developer Portal.
Create a bot :
Applications
.New Application
in the upper right corner and enter the name of the bot. After confirmation, enter the new page.Bot
.Privileged Gateway Intents
and click Save Changes
.Reset Token
button.Set up OAuth2 :
OAuth2
in the left column.URL Generator
in the left column.bot
and applications.commands
under SCOPES
.Administrator
under BOT PERMISSIONS
.Continue
> Authorize
.Obtain MongoDB Connection String
Create Cluster
.Network Access
page, click Add IP Address
and select Allow access from anywhere
.Database
page and click Connect
.database user
, click Choose a connection method
and select Connect your application
.<password>
with the password for the database user that you created earlier.Setting up the env file
If you go along with this, you can ignore the parts in the Project Execution
that explain how to generate and fill in the .env
.env
& .development.env
) you can run the command npm run setup-env:prod
.env
..example.env
file..env.development
file, you can run the command npm run setup-env:dev
and follow the steps above again.Project Execution
example.env
to .env
Bot
page on the Discord Developer Portal and click Reset Token
. Afterwards, create a .env
file within the root directory.token
variable inside the .env
file.mongodb
variable inside the .env
file.OAuth2
page and copy the CLIENT ID
.clientid
variable inside the .env
file.Copy Server ID
and paste it into the guildid
variable inside the .env
file.package.json
file and pay attention to the runnable commands listed under scripts
.npm run setup
. This will install the dependencies and give you a brief install guidenpm run prod
to run the file without using nodemon or npm run prod:nodemon
to run the bot with nodemon.Runnable commands (scripts)
Wipe Database -
To wipe the database that is connected via your mongoDB url, you can run the command npm run wipe-data:prod
, this brings up a menu which you can follow in order to either wipe the entire database from all it's data, or wipe all the data from individual schemas.
Update Packages -
To update all your dependencies, you can run the command npm run update-packages
, this cycles through the dependencies and updates one's which are out of date.
update-ytdl-core -
To update the version of the ytdl-core
package, you can run the command npm run update-ytdl-core
, this updates the package to the most recent version to ensure the music system works.
setup-env:prod -
To run the setup of the .env
file you can run the command npm run setup-env:prod
, this generates a script in the console that generates a .env
file and where you fill out the fields with whats required for the .env
file and it writes it in the file.
setup-env:dev -
To run the setup of the .env.development
file you can run the command npm run setup-env:dev
, this generates a script in the console that generates a .env.development
file and where you fill out the fields with whats required for the .env.development
file and it writes it in the file.
To set the advanced logs registry for the Testify audit-logs ( the event handler registers ) than follow this!
node_modules
=> discord-logs
=> lib
=> index.js
index.js
file for the discord logs package you'll want to copy and paste this code in below. "use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
const color = {
red: '\x1b[31m',
orange: '\x1b[38;5;202m',
yellow: '\x1b[33m',
green: '\x1b[32m',
blue: '\x1b[34m',
reset: '\x1b[0m',
pink: '\x1b[38;5;213m'
}
function getTimestamp() {
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
const discord_js_1 = require("discord.js");
const handlers_1 = require("./handlers");
let eventRegistered = false;
module.exports = (client, options) => __awaiter(void 0, void 0, void 0, function* () {
if (eventRegistered)
return;
eventRegistered = true;
const intents = new discord_js_1.IntentsBitField(client.options.intents);
/* HANDLE GUILDS EVENTS */
if (intents.has(discord_js_1.IntentsBitField.Flags.Guilds)) {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] ChannelUpdate event handler registered.`);
client.on('channelUpdate', (oldChannel, newChannel) => {
(0, handlers_1.handleChannelUpdateEvent)(client, oldChannel, newChannel);
});
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] GuildUpdate event handler registered.`);
client.on('guildUpdate', (oldGuild, newGuild) => {
(0, handlers_1.handleGuildUpdateEvent)(client, oldGuild, newGuild);
});
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] RoleUpdate event handler registered.`);
client.on('roleUpdate', (oldRole, newRole) => {
(0, handlers_1.handleRoleUpdateEvent)(client, oldRole, newRole);
});
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] ThreadUpdate event handler registered.`);
client.on('threadUpdate', (oldThread, newThread) => {
(0, handlers_1.handleThreadChannelUpdateEvent)(client, oldThread, newThread);
});
}
else {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`channelUpdate, guildUpdate, roleUpdate and threadUpdate event handlers not registered (missing Guilds intent).`);
}
/* HANDLE MEMBER EVENTS */
if (intents.has(discord_js_1.IntentsBitField.Flags.GuildMembers)) {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] GuildMemberUpdate event handler registered.`);
client.on('guildMemberUpdate', (oldMember, newMember) => {
(0, handlers_1.handleGuildMemberUpdateEvent)(client, oldMember, newMember);
});
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] UserUpdate event handler registered.`);
client.on('userUpdate', (oldUser, newUser) => {
(0, handlers_1.handleUserUpdateEvent)(client, oldUser, newUser);
});
}
else {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log('guildMemberUpdate, userUpdate event handlers not registered (missing GuildMembers intent).');
}
/* HANDLE MESSAGE UPDATE EVENTS */
if (intents.has(discord_js_1.IntentsBitField.Flags.GuildMessages && discord_js_1.IntentsBitField.Flags.MessageContent)) {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] MessageUpdate event handler registered.`);
client.on('messageUpdate', (oldMessage, newMessage) => {
(0, handlers_1.handleMessageUpdateEvent)(client, oldMessage, newMessage);
});
}
else {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log('messageUpdate event handler not registered (missing GuildMessages or MessageContent intent).');
}
/* HANDLE PRESENCE UPDATE EVENTS */
if (intents.has(discord_js_1.IntentsBitField.Flags.GuildPresences)) {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] PresenceUpdate event handler registered.`);
client.on('presenceUpdate', (oldPresence, newPresence) => {
(0, handlers_1.handlePresenceUpdateEvent)(client, oldPresence, newPresence);
});
}
else {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log('presenceUpdate event handler not registered (missing GuildPresences intent).');
}
/* HANDLE VOICE STATE UPDATE */
if (intents.has(discord_js_1.IntentsBitField.Flags.GuildVoiceStates)) {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log(`${color.pink}[${getTimestamp()}] ${color.reset}[AUDIT_LOGS] VoiceStateUpdate event handler registered.`);
client.on('voiceStateUpdate', (oldState, newState) => {
(0, handlers_1.handleVoiceStateUpdateEvent)(client, oldState, newState);
});
}
else {
if (options === null || options === void 0 ? void 0 : options.debug)
console.log('voiceStateUpdate event handler not registered (missing GuildVoiceStates intent).');
}
});
${color.pink}
to the color you'd like which are defined in the color variable.Connect with us on Discord for support / any related inquiry.
Released under the terms of MIT License license.
Thanks to TheLegendDev for the readme template from Nub Bot 💛