Our first task is of course to initialize the enmap correctly. In this case, we're attaching the settings to our client object so we can use it in different commands.
// start discord.js init// config with token and prefix.constconfig=require("./config.json"); // Code below supports and is tested under "stable" 11.3.xconstDiscord=require("discord.js");constclient=newDiscord.Client();// end discord.js init// Initialize the server configurationsconstEnmap=require('enmap');// I attach settings to client to allow for modular bot setups// In this example we'll leverage fetchAll:false and autoFetch:true for// best efficiency in memory usage. We also have to use cloneLevel:'deep'// to avoid our values to be "reference" to the default settings.// The explanation for why is complex - just go with it.client.settings =newEnmap({ name:"settings", fetchAll:false, autoFetch:true, cloneLevel:'deep', autoEnsure: { prefix:"!", modLogChannel:"mod-log", modRole:"Moderator", adminRole:"Administrator", welcomeChannel:"welcome", welcomeMessage:"Say hello to {{user}}, everyone!" }});
Events Setup
client.on("guildDelete", guild => {// When the bot leaves or is kicked, delete settings to prevent stale entries.client.settings.delete(guild.id);});client.on("guildMemberAdd", member => {// This executes when a member joins, so let's welcome them!// First, ensure the settings existclient.settings.ensure(member.guild.id, defaultSettings);// First, get the welcome message using get: let welcomeMessage =client.settings.get(member.guild.id,"welcomeMessage");// Our welcome message has a bit of a placeholder, let's fix that: welcomeMessage =welcomeMessage.replace("{{user}}",member.user.tag)// we'll send to the welcome channel.member.guild.channels.cache.find(channel =>channel.name ===client.settings.get(member.guild.id,"welcomeChannel")).send(welcomeMessage).catch(console.error);});
Message Event
The main event for our bot, where messages are received. Any error here will probably crash the bot on every message received, so be careful!
client.on("message",async (message) => {// This stops if it's not a guild (obviously), and we ignore all bots.// Pretty standard for any bot.if(!message.guild ||message.author.bot) return;// We get the value, and autoEnsure guarantees we have a value already.constguildConf=client.settings.get(message.guild.id);// Now we can use the values! We stop processing if the message does not// start with our prefix for this guild.if(message.content.indexOf(guildConf.prefix) !==0) return;//Then we use the config prefix to get our arguments and command:constargs=message.content.split(/\s+/g);constcommand=args.shift().slice(guildConf.prefix.length).toLowerCase();// Commands Go Here});
Command to set configurations
// Alright. Let's make a command! This one changes the value of any key// in the configuration.if(command ==="setconf") {// Command is admin only, let's grab the admin value: constadminRole=message.guild.roles.cache.find(role =>role.name ===guildConf.adminRole);if(!adminRole) returnmessage.reply("Administrator Role Not Found");// Then we'll exit if the user is not adminif(!message.member.roles.cache.has(adminRole.id)) {returnmessage.reply("You're not an admin, sorry!"); }// Let's get our key and value from the arguments. // This is array destructuring, by the way. const [prop,...value] = args;// Example: // prop: "prefix"// value: ["+"]// (yes it's an array, we join it further down!)// We can check that the key exists to avoid having multiple useless, // unused keys in the config:if(!client.settings.has(message.guild.id, prop)) {returnmessage.reply("This key is not in the configuration."); }// Now we can finally change the value. Here we only have strings for values // so we won't bother trying to make sure it's the right type and such. client.settings.set(message.guild.id,value.join(" "), prop);// We can confirm everything's done to the client.message.channel.send(`Guild configuration item ${prop} has been changed to:\n\`${value.join(" ")}\``); }
Command to show the configuration
if(command ==="showconf") {let configProps =Object.keys(guildConf).map(prop => {return`${prop} : ${guildConf[prop]}`; });message.channel.send(`The following are the server's current configuration: \`\`\`${configProps.join("\n")}\`\`\``); }