lookie here a private repo for the cool bot

This commit is contained in:
rhearmas 2019-11-26 16:22:24 -05:00
parent 579c0880a8
commit c07204b8ff
30 changed files with 1872 additions and 0 deletions

58
.eslintrc.json Normal file
View File

@ -0,0 +1,58 @@
{
"parserOptions": {
"ecmaVersion": 2017
},
"env": {
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"rules": {
"no-console": "off",
"indent": [
"error",
2,
{
"SwitchCase": 1
}
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"warn",
"double"
],
"semi": [
"warn",
"always"
],
"keyword-spacing": [
"error", {
"before": true,
"after": true
}
],
"space-before-blocks": [
"error", {
"functions":"always",
"keywords": "always",
"classes": "always"
}
],
"space-before-function-paren": [
"error", {
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}
],
"prefer-const": [
"error", {
"destructuring": "any",
"ignoreReadBeforeAssign": false
}
]
}
}

63
.gitignore vendored Normal file
View File

@ -0,0 +1,63 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
config.json
config.js
data/
test.js
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env

View File

@ -0,0 +1,100 @@
const Discord = require("discord.js");
exports.run = (client, message, args) => {
message.delete();
guild = message.guild;
let chnl = guild.channels.find(c => c.name === 'landing');
if(args[0]) {
chnl = args[0].substring("<#".length);
chnl = chnl.substring(chnl.length-1,0);
chnl = guild.channels.find(c => c.id === chnl);
}
async function clearLanding() {
let fetched;
fetched = await chnl.fetchMessages();
chnl.bulkDelete(fetched);
}
clearLanding();
const intro = new Discord.RichEmbed()
.setTitle("Introduction")
.setColor(0x00AE86)
.setDescription(`Welcome to the official **${guild.name} Discord server**! This is a Discord server that I personally run for all my shenanigans. This is the channel where I explain rules and stuff and other stuff.`)
.addField("IMPORTANT DISCLAIMER:", "This list does not constitute the full list of rules. With that in mind, try to use common sense and good judgement for any action you're about to take at all times.")
.addField("Before we go further...","I don't care if you use profanity here, since Discord only allows users who are at least 13 years of age. If you have a problem with this, then this isn't the discord server for you.")
.setThumbnail(guild.iconURL);
const textrules = new Discord.RichEmbed()
.setTitle("Text Channel Rules")
.setColor(0x8E8E38)
.addField("1.) Use common sense.","This means that you shouldn't be a jerk to others and have read the loose disclaimer.")
.addField("2.) No raiding.","Nobody here endorses raiding. Raiding this server or trying to rally other users to help you raid this server or another server is not allowed.")
.addField("3.) Do not attempt to destroy the server.","This includes vandalizing non-spam channels with spam or playing excessively loud music.")
.addField("4.) No discrimination.","This includes disrespecting people because of personal factors such as gender, sexual orientation, mental disabilities, race, age, location of residence, or anything else of the like.")
.addField("5.) Threats towards others are not allowed.","Do not attempt to cause others to feel endangered in this server. We want to provide a safe space for everyone here, so don't ruin it.")
.addField("6.) Abide by Discord's global platform rules.","This means that you should take the time to read the [Discord Terms of Service](https://discordapp.com/terms) and [Community Guidelines](https://discordapp.com/guidelines).")
.addField("7.) Don't complain about your punishments.","They were given for a valid reason. ModMail exists just in case a staff member falsely punishes you.")
.addField("8.) Loopholes aren't a thing, so don't go looking for them.","Don't be a wise-ass and just follow the rules. Don't test your boundaries, being here is a priviledge, not a right.")
.addField("9.) Advertising outside of the advertisement channel is not permitted.","This includes third-party services (that are not related to this Discord) or anything you or others have created, regardless of permission granted. Advertising other Discord servers -- or advertising **anything** in your playing status or through unsolicited DMs -- is strictly forbidden.")
.addField("10.) Don't cause beef with other members.","Don't send hate to other people if you see them as a bad person. Tolerate everyone here, even if you despise them, and don't engage in arguments.")
.addField("11.) Do not humiliate other people.","Mentioning previous drama or other situations any person was involved in is included.")
.addField("12.) No excuses for punishment.","The rule nullification system exists for a valid reason. Staff don't care until someone complains. Don't use this system as a way to attempt to circumvent a punishment.")
.addField("13.) Don't abuse your power.","You have power, that's cool. It does not, however, give you a one-way pass to do whatever you want.")
.addField("14.) Absolutely no NSFW content.","Shocking or graphic content, animal cruelty, and gore are not allowed whatsoever. Breaking this rule will result in a permanent ban on sight.");
const voicerules = new Discord.RichEmbed()
.setTitle("Voice Channel Rules")
.setColor(0x388E8E)
.addField("1.) Most text rules apply in the voice chat.","Don't go crazy because of the channels being different.")
.addField("2.) No loud audio.","Playing loud and/or annoying audio through your microphone or music bots is not allowed.")
.addField("3.) Be responsible.","Everyone in the server holds the right to report users in the voice channels to have them muted as needed.")
.addField("4.) Use common sense.","You can't escape this rule. Please don't ignore it.")
.addField("5.) Limit the usage of voice changers.","Don't fake what you sound like. We prevent discrimination, you're fine.");
const punishmentsystem = new Discord.RichEmbed()
.setTitle("Punishment System")
.setColor(0xC67171)
.setDescription("Break a rule and you will get warned or muted. Three warns from the moderation bot results in a kick, then a ban after going through the same process. Extreme offenders get worse punishments. If you have a higher-tier role such as Annoying, you may lose it until it's deemed necessary we give it back.")
.addBlankField()
.addField("IMPORTANT:","Staff hold a right to punish anyone how they see fit. Staff here are pretty lenient, just be a well rounded individual and respect others. The staff team can see any kind of deleted images because of the readily-available logging system they have at their disposal.");
const nullify = new Discord.RichEmbed()
.setTitle("Rule Nullification System")
.setColor(0xC5C1AA)
.setDescription("Self-explanatory information that this server has implemented. When a user breaks a rule, as long as everybody within the constituting area (voice/text channel, room, etcetera) is okay with that rule being broken, and/or is not reported, then essentially all rules broken are nullified until a complaining or reporting individual (or group of individuals) is present.")
.addField("HOWEVER...","This does NOT mean that you can break the rules first and ask questions later. Use this additional information at your own discretion, but if you misuse it or abuse it, the punishment is your own fault.")
.addBlankField()
.addField("Exceptions:","Discrimination and raiding are still not allowed. Plus, you must still abide by the Discord ToS and Community Guidelines.");
const annoying = new Discord.RichEmbed()
.setTitle("Annoying Role")
.setColor(0x9AFF9A)
.addField("What is the Annoying role?","The Annoying role is a role given out to users who meet certain requirements, and are usually well-known members of the community that don't need a staff position to pose as a great role model. This role grants additional permissions that normally require other roles.")
.addField("How do I get it?","Well, the requirements are as follows:\n• Level **50** (maximum yes) or above\n• No bans, warns or mutes for at least one month\n• Good community standing\n• Waited at least one month from last removal of the role")
.addField("What do I do when I meet these requirements?","If you meet the requirements, send a screenshot of your rank by copying the image sent by <@339254240012664832> after using `:?rank` in <#646840514389344257> and sending it through <@575252669443211264>. Be sure to ensure that we know why you're sending it!")
const links = new Discord.RichEmbed()
.setTitle("Important Links")
.setColor(0x8E388E)
.addField("Discord Server Invite Link","Use [this invite](https://discord.gg/4zJ8xqV) to invite others.")
.addField("Member Survey","After being here for a while, feel free to fill out [this form](https://goo.gl/forms/Gwa62lcu4zC7B8992).");
chnl.send({embed: intro});
chnl.send({embed: textrules});
chnl.send({embed: voicerules});
chnl.send({embed: punishmentsystem});
chnl.send({embed: nullify});
chnl.send({embed: annoying});
chnl.send({embed: links});
setTimeout(function(){chnl.send("*If you can't copy the invite link, here's the raw URL: https://discord.gg/4zJ8xqV*")},5000);
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "Bot Owner"
};
exports.help = {
name: "buildlanding",
category: "Channel Building",
description: "Builds the landing by purging the whole channel and sending embeds. Builds in first channel named **landing** if no arguments are provided.",
usage: "buildlanding channel"
};

View File

@ -0,0 +1,69 @@
const Discord = require("discord.js");
exports.run = (client, message, args) => {
message.delete();
guild = message.guild;
let chnl = message.channel;
if(args[0]) {
chnl = args[0].substring("<#".length);
chnl = chnl.substring(chnl.length-1,0);
chnl = guild.channels.find(c => c.id === chnl);
}
async function clearChannel() {
let fetched;
fetched = await chnl.fetchMessages();
chnl.bulkDelete(fetched);
}
clearChannel();
const intro = new Discord.RichEmbed()
.setTitle("Introduction")
.setColor(0x00AE86)
.setDescription(`Welcome to our staff team. We're great to have you. Part of your duties include keeping the server standing on two feet. But that doesn't mean your day is over yet. When taking part of our team, these guidelines must be met or exceeded, otherwise your position will be terminated. Please remember that this position is **voluntary**, and will most likely receive no compensation for your work.`);
const rules = new Discord.RichEmbed()
.setTitle("Staff Rules")
.setColor(0x8E8E38)
.addField("1.) Follow all this server's rules in #info.","Just because you're higher in the member list hierchy, doesn't mean you suddenly have a one-way ticket to total entitlement to break the rules. Set the good example for the nonadmins.")
.addField("2.) Don't be a hypocrite.","Hypocrisy is so, *so* incredibly common, and without properly addressing this, absolute chaos may ensue. With that said, remember that you need to always give yourself a taste of your own medicine before giving it to others.")
.addField("3.) Giveaways must require permission from a Head Admin or above.","Yeah, giving stuff away is fun, but don't abuse it.")
.addField("4.) Don't ping people unless it's justified.","Tying to this main server's rules, don't ping someone unless you're actively in conversation with them. Only ping higher-ups if someone's doing something wrong or you need help on what to do in a situation.")
.addField("5.) Don't abuse your power.","You aren't Stalin or Hitler or anything. Don't pull a fast one and go on murder sprees in-game or mass ban waves.")
.addField("6.) Don't do stuff to certain people because you \"don't like them\".","We all have our distaste for someone, but a community consensus for which bans are justified and which ones aren't. Warning people for stupid reasons isn't the right thing to do.")
.addField("7.) Changing parts of the server without prior permission is not allowed.","This isn't your server, it's the community's. Be righteous with what you do. You will need evidence to prove that you were permitted to do such actions.")
.addField("8.) Breaking Discord Terms of Service results in immediate action.","The Terms of Service are an important part to Discord. If you are exhibited to have assumed any behavior, you will be suspended from your priviledges.")
.addField("9.) Your rank doesn't let you ruin lower users' lives.","Do not use your rank as a way to get other people's attention or make them uncomfortable, **especially when trying to groom them like a predator**.");
const botinfo = new Discord.RichEmbed()
.setTitle("Management Information")
.setColor(0x388E8E)
.setDescription("We use @GalacticTest#2913 and @Carl-bot#1536 for management. Here's what you use them for.")
.addField("GalacticBot","**PREFIX: - (DASH)** | Moderation. Useful commands:\n`-warn user reason` | Example: `;warn rhearmas#9001 spamming`\n`-mute user [time]; [reason]` | Example: `-mute rhearmas#9001 5m spamming`\n`-kick user reason` | Example: `;kick rhearmas#9001 flooding channels`\n`-ban user reason` | Example: `-ban rhearmas#9001 abusing staff rank` | BANS WITH THIS ARE PERMANENT\n`-tempban user time; reason` | Example: `-tempban rhearmas#9001 1d; mass pinging` | **USE THIS BEFORE ANYTHING ELSE**")
.addField("Carl-Bot","**PREFIX: c/** | Fun, utilities, reminders. Useful commands:\n`c/remindme time reason`\n`c/reminder user`\n**Use `c/help commandname` to see more syntax information.**");
const importantInfo = new Discord.RichEmbed()
.setTitle("Super Important Information")
.setColor(0xC5C1AA)
.setDescription("As with the nonadmins, we hold the right to punish you as we see fit. Don't test your boundaries, and for the love of god, **do not use `@everyone` without any context**. People who don't tolerate pings may either leave the discord or will mute it, effectively missing out on events.")
.addField("Don't be afraid to ask questions!","Other staff members are always ready to help if you hit a snag and need someone higher up in the user hierarchy to handle something, or if that one button doesn't work or that lever doesn't go down all the way.");
chnl.send("\`<BEGIN_TAPE>\`");
chnl.send({embed: intro});
chnl.send({embed: rules});
chnl.send({embed: botinfo});
chnl.send({embed: importantInfo});
setTimeout(function(){chnl.send("\`<END_TAPE>\`")},1000);
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "Bot Owner"
};
exports.help = {
name: "staffinfo",
category: "Channel Building",
description: "Builds the staff rules channel in the mentioned channel. Builds in current if no arguments are provided.",
usage: "staffinfo channel"
};

18
commands/Fun/color.js Normal file
View File

@ -0,0 +1,18 @@
exports.run = async (client, message, args, level) => {
const response = await client.awaitReply(message, "Favourite Color?");
message.reply(`Oh, I really love ${response} too!`);
}
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "color",
category: "Fun",
description: "Who likes a color?",
usage: "color"
};

28
commands/Fun/talk.js Normal file
View File

@ -0,0 +1,28 @@
const Discord = require("discord.js");
exports.run = async (client, message, args) => {
msg = args.join(" ");
await message.delete();
if(args.length == 0)
return message.reply("Please insert a valid message.")
.then(msg => {
msg.delete(5000).catch(e => {e})
})
message.channel.send(msg);
}
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "Administrator"
};
exports.help = {
name: "talk",
category: "Fun",
description: "Talk as the bot in the current channel you're in.",
usage: "talk text"
};

97
commands/System/conf.js Normal file
View File

@ -0,0 +1,97 @@
const { inspect } = require("util");
/*
FOR GUILD SETTINGS SEE set.js !
This command is used to modify the bot's default configuration values, which affects all guilds.
If a default setting is not specifically overwritten by a guild, changing a default here will
change it for that guild. The `add` action adds a key to the configuration of every guild in
your bot. The `del` action removes the key also from every guild, and loses its value forever.
*/
exports.run = async (client, message, [action, key, ...value], level) => { // eslint-disable-line no-unused-vars
// Retrieve Default Values from the default settings in the bot.
const defaults = client.settings.get("default");
// Adding a new key adds it to every guild (it will be visible to all of them)
if (action === "add") {
if (!key) return message.reply("Please specify a key to add");
if (defaults[key]) return message.reply("This key already exists in the default settings");
if (value.length < 1) return message.reply("Please specify a value");
// `value` being an array, we need to join it first.
defaults[key] = value.join(" ");
// One the settings is modified, we write it back to the collection
client.settings.set("default", defaults);
message.reply(`${key} successfully added with the value of ${value.join(" ")}`);
} else
// Changing the default value of a key only modified it for guilds that did not change it to another value.
if (action === "edit") {
if (!key) return message.reply("Please specify a key to edit");
if (!defaults[key]) return message.reply("This key does not exist in the settings");
if (value.length < 1) return message.reply("Please specify a new value");
defaults[key] = value.join(" ");
client.settings.set("default", defaults);
message.reply(`${key} successfully edited to ${value.join(" ")}`);
} else
// WARNING: DELETING A KEY FROM THE DEFAULTS ALSO REMOVES IT FROM EVERY GUILD
// MAKE SURE THAT KEY IS REALLY NO LONGER NEEDED!
if (action === "del") {
if (!key) return message.reply("Please specify a key to delete.");
if (!defaults[key]) return message.reply("This key does not exist in the settings");
// Throw the 'are you sure?' text at them.
const response = await client.awaitReply(message, `Are you sure you want to permanently delete ${key} from all guilds? This **CANNOT** be undone.`);
// If they respond with y or yes, continue.
if (["y", "yes"].includes(response)) {
// We delete the default `key` here.
delete defaults[key];
client.settings.set("default", defaults);
// then we loop on all the guilds and remove this key if it exists.
// "if it exists" is done with the filter (if the key is present and it's not the default config!)
for (const [guildid, conf] of client.settings.filter((setting, id) => setting[key] && id !== "default")) {
delete conf[key];
client.settings.set(guildid, conf);
}
message.reply(`${key} was successfully deleted.`);
} else
// If they respond with n or no, we inform them that the action has been cancelled.
if (["n","no","cancel"].includes(response)) {
message.reply("Action cancelled.");
}
} else
// Display a key's default value
if (action === "get") {
if (!key) return message.reply("Please specify a key to view");
if (!defaults[key]) return message.reply("This key does not exist in the settings");
message.reply(`The value of ${key} is currently ${defaults[key]}`);
// Display all default settings.
} else {
await message.channel.send(`***__Bot Default Settings__***\n\`\`\`json\n${inspect(defaults)}\n\`\`\``);
}
};
exports.conf = {
enabled: true,
guildOnly: true,
aliases: ["defaults"],
permLevel: "Bot Admin"
};
exports.help = {
name: "conf",
category: "System",
description: "Modify the default configuration for all guilds.",
usage: "conf <view/get/edit> <key> <value>"
};

24
commands/System/eval.js Normal file
View File

@ -0,0 +1,24 @@
exports.run = async (client, message, args, level) => { // eslint-disable-line no-unused-vars
const code = args.join(" ");
try {
const evaled = eval(code);
const clean = await client.clean(client, evaled);
message.channel.send(`\`\`\`js\n${clean}\n\`\`\``);
} catch (err) {
message.channel.send(`\`ERROR\` \`\`\`xl\n${await client.clean(client, err)}\n\`\`\``);
}
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "Bot Owner"
};
exports.help = {
name: "eval",
category: "System",
description: "Evaluates arbitrary javascript.",
usage: "eval [...code]"
};

42
commands/System/help.js Normal file
View File

@ -0,0 +1,42 @@
exports.run = (client, message, args, level) => {
if (!args[0]) {
const myCommands = message.guild ? client.commands.filter(cmd => client.levelCache[cmd.conf.permLevel] <= level) : client.commands.filter(cmd => client.levelCache[cmd.conf.permLevel] <= level && cmd.conf.guildOnly !== true);
const commandNames = myCommands.keyArray();
const longest = commandNames.reduce((long, str) => Math.max(long, str.length), 0);
let currentCategory = "";
let output = `= Command List =\n\n[Use ${message.settings.prefix}help <commandname> for details]\n`;
const sorted = myCommands.array().sort((p, c) => p.help.category > c.help.category ? 1 : p.help.name > c.help.name && p.help.category === c.help.category ? 1 : -1 );
sorted.forEach( c => {
const cat = c.help.category.toProperCase();
if (currentCategory !== cat) {
output += `\u200b\n== ${cat} ==\n`;
currentCategory = cat;
}
output += `${message.settings.prefix}${c.help.name}${" ".repeat(longest - c.help.name.length)} :: ${c.help.description}\n`;
});
message.channel.send(output, {code: "asciidoc", split: { char: "\u200b" }});
} else {
let command = args[0];
if (client.commands.has(command)) {
command = client.commands.get(command);
if (level < client.levelCache[command.conf.permLevel]) return;
message.channel.send(`= ${command.help.name} = \n${command.help.description}\nusage:: ${command.help.usage}\naliases:: ${command.conf.aliases.join(", ")}\n= ${command.help.name} =`, {code:"asciidoc"});
}
}
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: ["h", "halp"],
permLevel: "User"
};
exports.help = {
name: "help",
category: "System",
description: "Displays all the available commands for your permission level.",
usage: "help [command]"
};

91
commands/System/set.js Normal file
View File

@ -0,0 +1,91 @@
// This command is to modify/edit guild configuration. Perm Level 3 for admins
// and owners only. Used for changing prefixes and role names and such.
// Note that there's no "checks" in this basic version - no config "types" like
// Role, String, Int, etc... It's basic, to be extended with your deft hands!
// Note the **destructuring** here. instead of `args` we have :
// [action, key, ...value]
// This gives us the equivalent of either:
// const action = args[0]; const key = args[1]; const value = args.slice(2);
// OR the same as:
// const [action, key, ...value] = args;
exports.run = async (client, message, [action, key, ...value], level) => { // eslint-disable-line no-unused-vars
// Retrieve current guild settings (merged) and overrides only.
const settings = message.settings;
const defaults = client.settings.get("default");
const overrides = client.settings.get(message.guild.id);
if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {});
// Edit an existing key value
if (action === "edit") {
// User must specify a key.
if (!key) return message.reply("Please specify a key to edit");
// User must specify a key that actually exists!
if (!defaults[key]) return message.reply("This key does not exist in the settings");
const joinedValue = value.join(" ");
// User must specify a value to change.
if (joinedValue.length < 1) return message.reply("Please specify a new value");
// User must specify a different value than the current one.
if (joinedValue === settings[key]) return message.reply("This setting already has that value!");
// If the guild does not have any overrides, initialize it.
if (!client.settings.has(message.guild.id)) client.settings.set(message.guild.id, {});
// Modify the guild overrides directly.
client.settings.set(message.guild.id, joinedValue, key);
// Confirm everything is fine!
message.reply(`${key} successfully edited to ${joinedValue}`);
} else
// Resets a key to the default value
if (action === "del" || action === "reset") {
if (!key) return message.reply("Please specify a key to reset.");
if (!defaults[key]) return message.reply("This key does not exist in the settings");
if (!overrides[key]) return message.reply("This key does not have an override and is already using defaults.");
// Good demonstration of the custom awaitReply method in `./modules/functions.js` !
const response = await client.awaitReply(message, `Are you sure you want to reset ${key} to the default value?`);
// If they respond with y or yes, continue.
if (["y", "yes"].includes(response.toLowerCase())) {
// We delete the `key` here.
client.settings.delete(message.guild.id, key);
message.reply(`${key} was successfully reset to default.`);
} else
// If they respond with n or no, we inform them that the action has been cancelled.
if (["n","no","cancel"].includes(response)) {
message.reply(`Your setting for \`${key}\` remains at \`${settings[key]}\``);
}
} else
if (action === "get") {
if (!key) return message.reply("Please specify a key to view");
if (!defaults[key]) return message.reply("This key does not exist in the settings");
const isDefault = !overrides[key] ? "\nThis is the default global default value." : "";
message.reply(`The value of ${key} is currently ${settings[key]}${isDefault}`);
} else {
// Otherwise, the default action is to return the whole configuration;
const array = [];
Object.entries(settings).forEach(([key, value]) => {
array.push(`${key}${" ".repeat(20 - key.length)}:: ${value}`);
});
await message.channel.send(`= Current Guild Settings =\n${array.join("\n")}`, {code: "asciidoc"});
}
};
exports.conf = {
enabled: true,
guildOnly: true,
aliases: ["setting", "settings", "conf"],
permLevel: "Administrator"
};
exports.help = {
name: "set",
category: "System",
description: "View or change settings for your server.",
usage: "set <view/get/edit> <key> <value>"
};

View File

@ -0,0 +1,27 @@
exports.run = async (client, message, args, level) => { // eslint-disable-line no-unused-vars
const response = await client.awaitReply(message, "**Are you sure you want to shut me down?** Respond with \`yes\` to proceed.")
const msg = question;
console.log(`Response is ${response}`);
if(response = "yes") {
await msg.edit(`Confirmed by ${message.author} Shutting down...`);
await Promise.all(client.commands.map(cmd =>
client.unloadCommand(cmd)
));
await msg.edit("Successfully shut down.");
process.exit(0);
}
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "Bot Owner"
};
exports.help = {
name: "shutdown",
category: "System",
description: "Shuts down the bot.",
usage: "shutdown"
};

View File

@ -0,0 +1,38 @@
exports.run = async (client, message, args, level) => {
let msgid = args[1];
let emoji = args[3];
guild = message.guild;
let chnl = message.channel;
if(args[0]) {
chnl = args[0].substring("<#".length);
chnl = chnl.substring(chnl.length-1,0);
chnl = guild.channels.find(c => c.id === chnl);
} else {
return message.reply("you need to use a valid channel.");
}
if(args[1] && ) {
} else {
return message.reply(`you need a valid message ID!`);
}
let amt = 3;
if(args[2] && typeof args[2] == 'number') {
amt = args[2];
}
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "getrandom",
category: "Utility",
description: "Gets a certain amount of users who reacted to a specific message with a specified emoji, and returns what it got in your current channel.",
usage: "getrandom channel msgid amount emoji"
};

View File

@ -0,0 +1,18 @@
exports.run = async (client, message, args, level) => {
const friendly = client.config.permLevels.find(l => l.level === level).name;
message.reply(`Your permission level is: ${level} - ${friendly}`);
};
exports.conf = {
enabled: true,
guildOnly: true,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "mylevel",
category: "Utility",
description: "Tells you your permission level for the current message location.",
usage: "mylevel"
};

18
commands/Utility/ping.js Normal file
View File

@ -0,0 +1,18 @@
exports.run = async (client, message, args, level) => { // eslint-disable-line no-unused-vars
const msg = await message.channel.send("Ping?");
msg.edit(`Pong! Latency is ${msg.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`);
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "ping",
category: "Utility",
description: "It like... Pings. Then Pongs. And it's not Ping Pong.",
usage: "ping"
};

View File

@ -0,0 +1,25 @@
exports.run = async (client, message, args, level) => {
if (!args || args.length < 1) return message.reply("why are you trying to reload a command without actually naming it?");
const command = client.commands.get(args[0]) || client.commands.get(client.aliases.get(args[0]));
let response = await client.unloadCommand(args[0]);
if (response) return message.reply(`Error Unloading: ${response}`);
response = client.loadCommand(command.help.name);
if (response) return message.reply(`Error Loading: ${response}`);
message.reply(`command \`${command.help.name}\` has been reloaded successfully.`);
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "Bot Admin"
};
exports.help = {
name: "reload",
category: "System",
description: "Reloads a command that\"s been modified.",
usage: "reload [command]"
};

29
commands/Utility/stats.js Normal file
View File

@ -0,0 +1,29 @@
const { version } = require("discord.js");
const moment = require("moment");
require("moment-duration-format");
exports.run = (client, message, args, level) => { // eslint-disable-line no-unused-vars
const duration = moment.duration(client.uptime).format(" D [days], H [hrs], m [mins], s [secs]");
message.channel.send(`= STATISTICS =
Mem Usage :: ${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB
Uptime :: ${duration}
Users :: ${client.users.size.toLocaleString()}
Servers :: ${client.guilds.size.toLocaleString()}
Channels :: ${client.channels.size.toLocaleString()}
Discord.js :: v${version}
Node :: ${process.version}`, {code: "asciidoc"});
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "stats",
category: "Utility",
description: "Gives some useful bot statistics.",
usage: "stats"
};

104
config.js.example Normal file
View File

@ -0,0 +1,104 @@
const config = {
// Bot Owner, level 10 by default. A User ID. Should never be anything else than the bot owner's ID.
"ownerID": "123456789123456",
// Bot Admins, level 9 by default. Array of user ID strings.
"admins": [],
// Bot Support, level 8 by default. Array of user ID strings
"support": [],
// Your Bot's Token. Available on https://discordapp.com/developers/applications/me
"token": "mfa.VkO_2G4Qv3T--NO--lWetW_tjND--TOKEN--QFTm6YGtzq9PH--4U--tG0",
// Default per-server settings. New guilds have these settings.
// DO NOT LEAVE ANY OF THESE BLANK, AS YOU WILL NOT BE ABLE TO UPDATE THEM
// VIA COMMANDS IN THE GUILD.
"defaultSettings" : {
"prefix": "-",
"modLogChannel": "mod-log",
"modRole": "Moderator",
"adminRole": "Administrator",
"systemNotice": "true", // This gives a notice when a user tries to run a command that they do not have permission to use.
"welcomeChannel": "welcome",
"welcomeMessage": "Say hello to {{user}}, everyone! We all need a warm welcome sometimes :D",
"welcomeEnabled": "false"
},
// PERMISSION LEVEL DEFINITIONS.
permLevels: [
// This is the lowest permisison level, this is for non-roled users.
{ level: 0,
name: "User",
// Don't bother checking, just return true which allows them to execute any command their
// level allows them to.
check: () => true
},
// This is your permission level, the staff levels should always be above the rest of the roles.
{ level: 2,
// This is the name of the role.
name: "Moderator",
// The following lines check the guild the message came from for the roles.
// Then it checks if the member that authored the message has the role.
// If they do return true, which will allow them to execute the command in question.
// If they don't then return false, which will prevent them from executing the command.
check: (message) => {
try {
const modRole = message.guild.roles.find(r => r.name.toLowerCase() === message.settings.modRole.toLowerCase());
if (modRole && message.member.roles.has(modRole.id)) return true;
} catch (e) {
return false;
}
}
},
{ level: 3,
name: "Administrator",
check: (message) => {
try {
const adminRole = message.guild.roles.find(r => r.name.toLowerCase() === message.settings.adminRole.toLowerCase());
return (adminRole && message.member.roles.has(adminRole.id));
} catch (e) {
return false;
}
}
},
// This is the server owner.
{ level: 4,
name: "Server Owner",
// Simple check, if the guild owner id matches the message author's ID, then it will return true.
// Otherwise it will return false.
check: (message) => message.channel.type === "text" ? (message.guild.ownerID === message.author.id ? true : false) : false
},
// Bot Support is a special inbetween level that has the equivalent of server owner access
// to any server they joins, in order to help troubleshoot the bot on behalf of owners.
{ level: 8,
name: "Bot Support",
// The check is by reading if an ID is part of this array. Yes, this means you need to
// change this and reboot the bot to add a support user. Make it better yourself!
check: (message) => config.support.includes(message.author.id)
},
// Bot Admin has some limited access like rebooting the bot or reloading commands.
{ level: 9,
name: "Bot Admin",
check: (message) => config.admins.includes(message.author.id)
},
// This is the bot owner, this should be the highest permission level available.
// The reason this should be the highest level is because of dangerous commands such as eval
// or exec (if the owner has that).
{ level: 10,
name: "Bot Owner",
// Another simple check, compares the message author id to the one stored in the config file.
check: (message) => message.client.config.ownerID === message.author.id
}
]
};
module.exports = config;

87
config_base.txt Normal file
View File

@ -0,0 +1,87 @@
const config = {
// Bot Owner, level 10 by default. A User ID. Should never be anything else than the bot owner's ID.
"ownerID": "{{ownerID}}",
// Bot Admins, level 9 by default. Array of user ID strings.
"admins": [],
// Bot Support, level 8 by default. Array of user ID strings
"support": [],
// Your Bot's Token. Available on https://discordapp.com/developers/applications/me
"token": {{token}},
// PERMISSION LEVEL DEFINITIONS.
permLevels: [
// This is the lowest permisison level, this is for non-roled users.
{ level: 0,
name: "User",
// Don't bother checking, just return true which allows them to execute any command their
// level allows them to.
check: () => true
},
// This is your permission level, the staff levels should always be above the rest of the roles.
{ level: 2,
// This is the name of the role.
name: "Moderator",
// The following lines check the guild the message came from for the roles.
// Then it checks if the member that authored the message has the role.
// If they do return true, which will allow them to execute the command in question.
// If they don't then return false, which will prevent them from executing the command.
check: (message) => {
try {
const modRole = message.guild.roles.find(r => r.name.toLowerCase() === message.settings.modRole.toLowerCase());
if (modRole && message.member.roles.has(modRole.id)) return true;
} catch (e) {
return false;
}
}
},
{ level: 3,
name: "Administrator",
check: (message) => {
try {
const adminRole = message.guild.roles.find(r => r.name.toLowerCase() === message.settings.adminRole.toLowerCase());
return (adminRole && message.member.roles.has(adminRole.id));
} catch (e) {
return false;
}
}
},
// This is the server owner.
{ level: 4,
name: "Server Owner",
// Simple check, if the guild owner id matches the message author's ID, then it will return true.
// Otherwise it will return false.
check: (message) => message.channel.type === "text" ? (message.guild.ownerID === message.author.id ? true : false) : false
},
// Bot Support is a special inbetween level that has the equivalent of server owner access
// to any server they joins, in order to help troubleshoot the bot on behalf of owners.
{ level: 8,
name: "Bot Support",
// The check is by reading if an ID is part of this array. Yes, this means you need to
// change this and reboot the bot to add a support user. Make it better yourself!
check: (message) => config.support.includes(message.author.id)
},
// Bot Admin has some limited access like rebooting the bot or reloading commands.
{ level: 9,
name: "Bot Admin",
check: (message) => config.admins.includes(message.author.id)
},
// This is the bot owner, this should be the highest permission level available.
// The reason this should be the highest level is because of dangerous commands such as eval
// or exec (if the owner has that).
{ level: 10,
name: "Bot Owner",
// Another simple check, compares the message author id to the one stored in the config file.
check: (message) => message.client.config.ownerID === message.author.id
}
]
};
module.exports = config;

3
events/error.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = async (client, error) => {
client.logger.log(`An error event was sent by Discord.js: \n${JSON.stringify(error)}`, "error");
};

5
events/guildCreate.js Normal file
View File

@ -0,0 +1,5 @@
// This event executes when a new guild (server) is joined.
module.exports = (client, guild) => {
client.logger.cmd(`[GUILD JOIN] ${guild.name} (${guild.id}) added the bot. Owner: ${guild.owner.user.tag} (${guild.owner.user.id})`);
};

9
events/guildDelete.js Normal file
View File

@ -0,0 +1,9 @@
// This event executes when a new guild (server) is left.
module.exports = (client, guild) => {
client.logger.cmd(`[GUILD LEAVE] ${guild.name} (${guild.id}) removed the bot.`);
if (client.settings.has(guild.id)) {
client.settings.delete(guild.id);
}
};

16
events/guildMemberAdd.js Normal file
View File

@ -0,0 +1,16 @@
// This event executes when a new member joins a server. Let's welcome them!
module.exports = (client, member) => {
// Load the guild's settings
const settings = client.getSettings(member.guild);
// If welcome is off, don't proceed (don't welcome the user)
if (settings.welcomeEnabled !== "true") return;
// Replace the placeholders in the welcome message with actual data
const welcomeMessage = settings.welcomeMessage.replace("{{user}}", member.user.tag);
// Send the welcome message to the welcome channel
// There's a place for more configs here.
member.guild.channels.find(c => c.name === settings.welcomeChannel).send(welcomeMessage).catch(console.error);
};

70
events/message.js Normal file
View File

@ -0,0 +1,70 @@
// The MESSAGE event runs anytime a message is received
// Note that due to the binding of client to every event, every event
// goes `client, other, args` when this function is run.
module.exports = async (client, message) => {
// It's good practice to ignore other bots. This also makes your bot ignore itself
// and not get into a spam loop (we call that "botception").
if (message.author.bot) return;
// Grab the settings for this server from Enmap.
// If there is no guild, get default conf (DMs)
const settings = message.settings = client.getSettings(message.guild);
// Checks if the bot was mentioned, with no message after it, returns the prefix.
const prefixMention = new RegExp(`^<@!?${client.user.id}>( |)$`);
if (message.content.match(prefixMention)) {
return message.reply(`My prefix on this guild is \`${settings.prefix}\``);
}
// Also good practice to ignore any message that does not start with our prefix,
// which is set in the configuration file.
if (message.content.indexOf(settings.prefix) !== 0) return;
// Here we separate our "command" name, and our "arguments" for the command.
// e.g. if we have the message "+say Is this the real life?" , we'll get the following:
// command = say
// args = ["Is", "this", "the", "real", "life?"]
const args = message.content.slice(settings.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
// If the member on a guild is invisible or not cached, fetch them.
if (message.guild && !message.member) await message.guild.fetchMember(message.author);
// Get the user or member's permission level from the elevation
const level = client.permlevel(message);
// Check whether the command, or alias, exist in the collections defined
// in app.js.
const cmd = client.commands.get(command) || client.commands.get(client.aliases.get(command));
// using this const varName = thing OR otherthign; is a pretty efficient
// and clean way to grab one of 2 values!
if (!cmd) return;
// Some commands may not be useable in DMs. This check prevents those commands from running
// and return a friendly error message.
if (cmd && !message.guild && cmd.conf.guildOnly)
return message.channel.send("This command is unavailable via private message. Please run this command in a guild.");
if (level < client.levelCache[cmd.conf.permLevel]) {
if (settings.systemNotice === "true") {
return message.channel.send(`You do not have permission to use this command.
Your permission level is ${level} (${client.config.permLevels.find(l => l.level === level).name})
This command requires level ${client.levelCache[cmd.conf.permLevel]} (${cmd.conf.permLevel})`);
} else {
return;
}
}
// To simplify message arguments, the author's level is now put on level (not member so it is supported in DMs)
// The "level" command module argument will be deprecated in the future.
message.author.permLevel = level;
message.flags = [];
while (args[0] && args[0][0] === "-") {
message.flags.push(args.shift().slice(1));
}
// If the command exists, **AND** the user has permission, run it.
client.logger.cmd(`[CMD] ${client.config.permLevels.find(l => l.level === level).name} ${message.author.username} (${message.author.id}) ran command ${cmd.help.name}`);
cmd.run(client, message, args, level);
};

7
events/ready.js Normal file
View File

@ -0,0 +1,7 @@
module.exports = async client => {
// Log that the bot is online.
client.logger.log(`${client.user.tag}, ready to serve ${client.users.size} users in ${client.guilds.size} servers.`, "ready");
// Make the bot "play the game" which is the help command with default prefix.
client.user.setActivity(`${client.settings.get("default").prefix}help`, {type: "PLAYING"});
};

64
index.js Normal file
View File

@ -0,0 +1,64 @@
if (Number(process.version.slice(1).split(".")[0]) < 8) throw new Error("Node 8.0.0 or higher is required. Update Node on your system.");
const Discord = require("discord.js");
const { promisify } = require("util");
const readdir = promisify(require("fs").readdir);
const Enmap = require("enmap");
const path = require("path");
const client = new Discord.Client();
client.config = require("./config.js");
client.logger = require("./modules/Logger");
require("./modules/functions.js")(client);
client.commands = new Enmap();
client.aliases = new Enmap();
client.settings = new Enmap({name: "settings"});
async function crawl(directory, filesArray) {
const dirs = await readdir(directory, {
withFileTypes: true
});
for (let i = 0; i < dirs.length; i++) {
const currentDir = dirs[i];
const newPath = path.join(directory, currentDir.name);
if (currentDir.isDirectory()) {
await crawl(newPath, filesArray);
}
else {
filesArray.push(newPath);
}
}
}
const init = async () => {
let cmdFiles = []
await crawl("commands",cmdFiles);
client.logger.log(`Loading a total of ${cmdFiles.length} commands.`);
cmdFiles.forEach(f => {
if (!f.endsWith(".js")) return;
const response = client.loadCommand(f);
if (response) console.log(response);
});
const evtFiles = await readdir("./events/");
client.logger.log(`Loading a total of ${evtFiles.length} events.`);
evtFiles.forEach(file => {
const eventName = file.split(".")[0];
client.logger.log(`Loading Event: ${eventName}`);
const event = require(`./events/${file}`);
client.on(eventName, event.bind(null, client));
});
client.levelCache = {};
for (let i = 0; i < client.config.permLevels.length; i++) {
const thisLevel = client.config.permLevels[i];
client.levelCache[thisLevel.name] = thisLevel.level;
}
client.login(client.config.token);
};
init();

38
modules/Logger.js Normal file
View File

@ -0,0 +1,38 @@
/*
Logger class for easy and aesthetically pleasing console logging
*/
const chalk = require("chalk");
const moment = require("moment");
exports.log = (content, type = "log") => {
const timestamp = `[${moment().format("YYYY-MM-DD HH:mm:ss")}]:`;
switch (type) {
case "log": {
return console.log(`${timestamp} ${chalk.bgBlue(type.toUpperCase())} ${content} `);
}
case "warn": {
return console.log(`${timestamp} ${chalk.black.bgYellow(type.toUpperCase())} ${content} `);
}
case "error": {
return console.log(`${timestamp} ${chalk.bgRed(type.toUpperCase())} ${content} `);
}
case "debug": {
return console.log(`${timestamp} ${chalk.green(type.toUpperCase())} ${content} `);
}
case "cmd": {
return console.log(`${timestamp} ${chalk.black.bgWhite(type.toUpperCase())} ${content}`);
}
case "ready": {
return console.log(`${timestamp} ${chalk.black.bgGreen(type.toUpperCase())} ${content}`);
}
default: throw new TypeError("Logger type must be either warn, debug, log, ready, cmd or error.");
}
};
exports.error = (...args) => this.log(...args, "error");
exports.warn = (...args) => this.log(...args, "warn");
exports.debug = (...args) => this.log(...args, "debug");
exports.cmd = (...args) => this.log(...args, "cmd");

126
modules/functions.js Normal file
View File

@ -0,0 +1,126 @@
module.exports = (client) => {
client.permlevel = message => {
let permlvl = 0;
const permOrder = client.config.permLevels.slice(0).sort((p, c) => p.level < c.level ? 1 : -1);
while (permOrder.length) {
const currentLevel = permOrder.shift();
if (message.guild && currentLevel.guildOnly) continue;
if (currentLevel.check(message)) {
permlvl = currentLevel.level;
break;
}
}
return permlvl;
};
const defaultSettings = {
"prefix": "~",
"modLogChannel": "mod-log",
"modRole": "Moderator",
"adminRole": "Administrator",
"systemNotice": "true",
"welcomeChannel": "welcome",
"welcomeMessage": "Say hello to {{user}}, everyone! We all need a warm welcome sometimes :D",
"welcomeEnabled": "false"
};
client.getSettings = (guild) => {
client.settings.ensure("default", defaultSettings);
if(!guild) return client.settings.get("default");
const guildConf = client.settings.get(guild.id) || {};
return ({...client.settings.get("default"), ...guildConf});
};
client.awaitReply = async (msg, question, limit = 60000) => {
const filter = m => m.author.id === msg.author.id;
await msg.channel.send(question);
try {
const collected = await msg.channel.awaitMessages(filter, { max: 1, time: limit, errors: ["time"] });
return collected.first().content;
} catch (e) {
return false;
}
};
client.clean = async (client, text) => {
if (text && text.constructor.name == "Promise")
text = await text;
if (typeof text !== "string")
text = require("util").inspect(text, {depth: 1});
text = text
.replace(/`/g, "`" + String.fromCharCode(8203))
.replace(/@/g, "@" + String.fromCharCode(8203))
.replace(client.token, "mfa.VkO_2G4Qv3T--NO--lWetW_tjND--TOKEN--QFTm6YGtzq9PH--4U--tG0");
return text;
};
client.loadCommand = (commandName) => {
try {
client.logger.log(`Loading Command: ${commandName}`);
const props = require(`../${commandName}`);
if (props.init) {
props.init(client);
}
client.commands.set(props.help.name, props);
props.conf.aliases.forEach(alias => {
client.aliases.set(alias, props.help.name);
});
return false;
} catch (e) {
return `Unable to load command ${commandName}: ${e}`;
}
};
client.unloadCommand = async (commandName) => {
let command;
if (client.commands.has(commandName)) {
command = client.commands.get(commandName);
} else if (client.aliases.has(commandName)) {
command = client.commands.get(client.aliases.get(commandName));
}
if (!command) return `The command \`${commandName}\` doesn\'t seem to exist, nor is it an alias. Try again!`;
if (command.shutdown) {
await command.shutdown(client);
}
const mod = require.cache[require.resolve(`../${command.help.category}/${command.help.name}`)];
delete require.cache[require.resolve(`../${command.help.category}/${command.help.name}.js`)];
for (let i = 0; i < mod.parent.children.length; i++) {
if (mod.parent.children[i] === mod) {
mod.parent.children.splice(i, 1);
break;
}
}
return false;
};
Object.defineProperty(String.prototype, "toProperCase", {
value: function() {
return this.replace(/([^\W_]+[^\s-]*) */g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
}
});
Object.defineProperty(Array.prototype, "random", {
value: function() {
return this[Math.floor(Math.random() * this.length)];
}
});
client.wait = require("util").promisify(setTimeout);
process.on("uncaughtException", (err) => {
const errorMsg = err.stack.replace(new RegExp(`${__dirname}/`, "g"), "./");
client.logger.error(`Uncaught Exception: ${errorMsg}`);
console.error(err);
process.exit(1);
});
process.on("unhandledRejection", err => {
client.logger.error(`Unhandled rejection: ${err}`);
console.error(err);
});
};

493
package-lock.json generated Normal file
View File

@ -0,0 +1,493 @@
{
"name": "guidebot",
"version": "2.3.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@cush/relative": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@cush/relative/-/relative-0.1.0.tgz",
"integrity": "sha512-pnF2c2hhHyC520CmYYKq3hGOS0kipkGBgRnp3z7wx7lDzykaUwQW3wPQmiX9YtbHUcgUu1qQtzstixmeYMwQoA=="
},
"ansi-escapes": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ=="
},
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
},
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
},
"better-sqlite3": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-5.4.0.tgz",
"integrity": "sha512-Uj1ZYOcq1GtFyFgJgqMVDoDLTy1B1pM9+bULnlX8szRX4cPjE/7JbKxCzQGhYlZlLkHQvtXXhCZ3skqsQ2byMA==",
"requires": {
"integer": "^2.1.0",
"tar": "^4.4.6"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
},
"chownr": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
},
"cli-cursor": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
"requires": {
"restore-cursor": "^2.0.0"
}
},
"cli-width": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
},
"crawl": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/crawl/-/crawl-0.3.1.tgz",
"integrity": "sha1-ljAMnWoY60nBbgM98+B9xYYfVd0=",
"requires": {
"colors": ">= 0.6.0-1",
"first": "0.0.x",
"mime": "1.2.x",
"node_hash": "0.2.x",
"optimist": "0.3.x",
"prettyjson": "0.7.x",
"simplecrawler": "0.0.x",
"underscore": "1.4.x"
}
},
"discord.js": {
"version": "11.5.1",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.5.1.tgz",
"integrity": "sha512-tGhV5xaZXE3Z+4uXJb3hYM6gQ1NmnSxp9PClcsSAYFVRzH6AJH74040mO3afPDMWEAlj8XsoPXXTJHTxesqcGw==",
"requires": {
"long": "^4.0.0",
"prism-media": "^0.0.3",
"snekfetch": "^3.6.4",
"tweetnacl": "^1.0.0",
"ws": "^6.0.0"
}
},
"enmap": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/enmap/-/enmap-5.0.0.tgz",
"integrity": "sha512-ntA4u4/p4FYpfFHAHiuLviIgVJYa5Bb1m5J9xkA1Ch3dgarHIqxdsDbzQS9PM3z9iF2yae/ud8uKQDMYPmRx2w==",
"requires": {
"lodash": "^4.17.11"
}
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"external-editor": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
"integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
"requires": {
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
"tmp": "^0.0.33"
}
},
"figures": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
"requires": {
"escape-string-regexp": "^1.0.5"
}
},
"first": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/first/-/first-0.0.3.tgz",
"integrity": "sha1-EpqTHr+B01BdhffAXHti0MTOag4="
},
"fs-minipass": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.6.tgz",
"integrity": "sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==",
"requires": {
"minipass": "^2.2.1"
}
},
"glob-regex": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/glob-regex/-/glob-regex-0.3.2.tgz",
"integrity": "sha512-m5blUd3/OqDTWwzBBtWBPrGlAzatRywHameHeekAZyZrskYouOGdNB8T/q6JucucvJXtOuyHIn0/Yia7iDasDw=="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"inquirer": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz",
"integrity": "sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==",
"requires": {
"ansi-escapes": "^3.2.0",
"chalk": "^2.4.2",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
"external-editor": "^3.0.3",
"figures": "^2.0.0",
"lodash": "^4.17.11",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rxjs": "^6.4.0",
"string-width": "^2.1.0",
"strip-ansi": "^5.1.0",
"through": "^2.3.6"
}
},
"integer": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/integer/-/integer-2.1.0.tgz",
"integrity": "sha512-vBtiSgrEiNocWvvZX1RVfeOKa2mCHLZQ2p9nkQkQZ/BvEiY+6CcUz0eyjvIiewjJoeNidzg2I+tpPJvpyspL1w=="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
},
"lodash": {
"version": "4.17.14",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw=="
},
"long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"mime": {
"version": "1.2.11",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz",
"integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA="
},
"mimic-fn": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"minipass": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
},
"minizlib": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz",
"integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==",
"requires": {
"minipass": "^2.2.1"
}
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"moment-duration-format": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/moment-duration-format/-/moment-duration-format-2.3.2.tgz",
"integrity": "sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ=="
},
"mute-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
},
"node_hash": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/node_hash/-/node_hash-0.2.0.tgz",
"integrity": "sha1-nqZNeh8xb7+QPlzVOuCtL/2qZ9k="
},
"onetime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
"requires": {
"mimic-fn": "^1.0.0"
}
},
"optimist": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
"integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=",
"requires": {
"wordwrap": "~0.0.2"
}
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"prettyjson": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-0.7.1.tgz",
"integrity": "sha1-LDjuqhXktq2wPrvmYkAtHqI5xcM=",
"requires": {
"colors": "0.6.0-1"
},
"dependencies": {
"colors": {
"version": "0.6.0-1",
"resolved": "https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz",
"integrity": "sha1-bbtozri8YPKzE9zFzhWZ8G0Z5no="
}
}
},
"prism-media": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.3.tgz",
"integrity": "sha512-c9KkNifSMU/iXT8FFTaBwBMr+rdVcN+H/uNv1o+CuFeTThNZNTOrQ+RgXA1yL/DeLk098duAeRPP3QNPNbhxYQ=="
},
"recrawl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/recrawl/-/recrawl-2.0.0.tgz",
"integrity": "sha512-PmL1uxEDduB/qqWc06KZzGJ4j//sXAuMlTcNJFFAEMTffJIFrzFghOxkgHU8+auKOUILEdbyfuEvFyoeu4mJgQ==",
"requires": {
"@cush/relative": "^0.1.0",
"glob-regex": "^0.3.0",
"tslib": "^1.9.3"
}
},
"restore-cursor": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
"requires": {
"onetime": "^2.0.0",
"signal-exit": "^3.0.2"
}
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
"integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
"requires": {
"is-promise": "^2.1.0"
}
},
"rxjs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz",
"integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==",
"requires": {
"tslib": "^1.9.0"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"simplecrawler": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/simplecrawler/-/simplecrawler-0.0.10.tgz",
"integrity": "sha1-1EzZFb3cyO4fCSDXpbxHuClwvuk="
},
"snekfetch": {
"version": "3.6.4",
"resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.4.tgz",
"integrity": "sha512-NjxjITIj04Ffqid5lqr7XdgwM7X61c/Dns073Ly170bPQHLm6jkmelye/eglS++1nfTWktpP6Y2bFXjdPlQqdw=="
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
},
"dependencies": {
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "^3.0.0"
}
}
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": {
"ansi-regex": "^4.1.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
}
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
},
"tar": {
"version": "4.4.10",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz",
"integrity": "sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==",
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
"minipass": "^2.3.5",
"minizlib": "^1.2.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.2",
"yallist": "^3.0.3"
}
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"requires": {
"os-tmpdir": "~1.0.2"
}
},
"tslib": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
},
"tweetnacl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.1.tgz",
"integrity": "sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A=="
},
"underscore": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
"integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ="
},
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
},
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
"requires": {
"async-limiter": "~1.0.0"
}
},
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
}
}
}

37
package.json Normal file
View File

@ -0,0 +1,37 @@
{
"name": "guidebot",
"version": "2.3.6",
"description": "A boilerplate example bot with command handler and reloadable commands. Updated and Maintained by the Idiot's Guide Community",
"main": "index.js",
"scripts": {
"start": "node index.js",
"postinstall": "node setup.js"
},
"engines": {
"node": ">=8"
},
"repository": {
"type": "git",
"url": "git+https://github.com/An-Idiots-Guide/guidebot.git"
},
"author": "Evelyne Lachance <eslachance@gmail.com> (http://evie.codes)",
"contributors": [
"York (http://anidiots.guide)"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/An-Idiots-Guide/guidebot/issues"
},
"homepage": "https://github.com/An-Idiots-Guide/guidebot#readme",
"dependencies": {
"better-sqlite3": "^5.4.0",
"chalk": "^2.4.2",
"crawl": "^0.3.1",
"discord.js": "^11.5.1",
"enmap": "^5.0.0",
"inquirer": "^6.3.1",
"moment": "^2.24.0",
"moment-duration-format": "^2.3.2",
"recrawl": "^2.0.0"
}
}

68
setup.js Normal file
View File

@ -0,0 +1,68 @@
const inquirer = require("inquirer");
const Enmap = require("enmap");
const fs = require("fs");
let baseConfig = fs.readFileSync("./config_base.txt", "utf8");
const defaultSettings = {
"prefix": "/",
"modLogChannel": "nsa-survellience-system",
"modRole": "modinator",
"adminRole": "adminator",
"systemNotice": "true",
"welcomeChannel": "welcome",
"welcomeMessage": "Say hello to {{user}}, everyone! We all need a warm welcome sometimes :D",
"welcomeEnabled": "false"
};
const settings = new Enmap({
name: "settings",
cloneLevel: 'deep',
ensureProps: true
});
let prompts = [
{
type: "list",
name: "resetDefaults",
message: "Do you want to reset default settings?",
choices: ["Yes", "No"]
},
{
type: "input",
name: "token",
message: "Please enter the bot token from the application page."
},
{
type: "input",
name: "ownerID",
message: "Please enter the bot owner's User ID"
},
];
(async function () {
console.log("Setting Up Cardboard Bot Configuration...");
await settings.defer;
if (!settings.has("default")) {
prompts = prompts.slice(1);
console.log("First Start! Inserting default guild settings in the database...");
await settings.set("default", defaultSettings);
}
const answers = await inquirer.prompt(prompts);
if (answers.resetDefaults && answers.resetDefaults === "Yes") {
console.log("Resetting default guild settings...");
await settings.set("default", defaultSettings);
}
baseConfig = baseConfig
.replace("{{ownerID}}", answers.ownerID)
.replace("{{token}}", `"${answers.token}"`);
fs.writeFileSync("./config.js", baseConfig);
console.log("REMEMBER TO NEVER SHARE YOUR TOKEN WITH ANYONE!");
console.log("Configuration has been written, enjoy!");
await settings.close();
}());