new stuff
This commit is contained in:
commit
a5b6425af1
22 changed files with 1375 additions and 0 deletions
19
bot/base/Command.js
Normal file
19
bot/base/Command.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
class Command {
|
||||
|
||||
constructor (client, {
|
||||
name = null,
|
||||
description = "No description provided.",
|
||||
category = "Miscellaneous",
|
||||
usage = "No usage provided.",
|
||||
enabled = true,
|
||||
guildOnly = false,
|
||||
devOnly = false,
|
||||
aliases = new Array(),
|
||||
permLevel = "User"
|
||||
}) {
|
||||
this.client = client;
|
||||
this.conf = { enabled, guildOnly, devOnly, aliases, permLevel };
|
||||
this.help = { name, description, category, usage };
|
||||
}
|
||||
}
|
||||
module.exports = Command;
|
25
bot/commands/Core/ping.js
Normal file
25
bot/commands/Core/ping.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
const Command = require("../../base/Command.js");
|
||||
|
||||
class Ping extends Command {
|
||||
constructor (client) {
|
||||
super(client, {
|
||||
name: "ping",
|
||||
description: "Latency and API response times.",
|
||||
usage: "ping",
|
||||
aliases: ["pong"]
|
||||
});
|
||||
}
|
||||
|
||||
async run (message, args, level) { // eslint-disable-line no-unused-vars
|
||||
try {
|
||||
const msg = await message.channel.send('Pinging...')
|
||||
msg.edit(
|
||||
`Pong! \`${msg.createdTimestamp - message.createdTimestamp}ms\` (💗 \`${Math.round(this.client.ws.ping)}ms\`)`
|
||||
)
|
||||
} catch (err) {
|
||||
this.client.logger.err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Ping;
|
37
bot/commands/Developer/eval.js
Normal file
37
bot/commands/Developer/eval.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
const Command = require("../../base/Command.js");
|
||||
const Discord = require("discord.js");
|
||||
|
||||
class Eval extends Command {
|
||||
constructor (client) {
|
||||
super(client, {
|
||||
description: "Evaluates arbitrary Javascript.",
|
||||
usage: "eval <expression>",
|
||||
aliases: ["ev"],
|
||||
permLevel: "Bot Owner",
|
||||
devOnly: true
|
||||
});
|
||||
}
|
||||
|
||||
async run (message, args, data) { // eslint-disable-line no-unused-vars
|
||||
const code = args.join(" ");
|
||||
try {
|
||||
const evaled = eval(code);
|
||||
const clean = await this.client.util.clean(evaled);
|
||||
const MAX_CHARS = 3 + 2 + clean.length + 3;
|
||||
if (MAX_CHARS > 2000) {
|
||||
message.channel.send({ files: [new Discord.MessageAttachment(Buffer.from(clean), "output.txt")] });
|
||||
}
|
||||
message.channel.send(`\`\`\`js\n${clean}\n\`\`\``);
|
||||
} catch (err) {
|
||||
const e = await this.client.util.clean(err);
|
||||
const MAX_CHARS = 1 + 5 + 1 + 3 + e.length + 3;
|
||||
console.log(MAX_CHARS);
|
||||
if (MAX_CHARS > 2000) {
|
||||
return message.channel.send({ files: [new Discord.MessageAttachment(Buffer.from(e), "error.txt")] });
|
||||
}
|
||||
message.channel.send(`\`ERROR\` \`\`\`xl\n${e}\n\`\`\``);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Eval;
|
9
bot/events/error.js
Normal file
9
bot/events/error.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
module.exports = class {
|
||||
constructor (client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async run (error) {
|
||||
this.client.logger.log(`An error event was sent by Discord.js: \n${JSON.stringify(error)}`, "error");
|
||||
}
|
||||
};
|
46
bot/events/message.js
Normal file
46
bot/events/message.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
// 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 = class {
|
||||
constructor (client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async run (message) {
|
||||
if (message.author.bot) return;
|
||||
|
||||
let data = new Object();
|
||||
|
||||
if (message.content.indexOf(this.client.config.defaultPrefix) !== 0) return;
|
||||
|
||||
const args = message.content.slice(this.client.config.defaultPrefix.length).trim().split(/ +/g);
|
||||
const command = args.shift().toLowerCase();
|
||||
|
||||
// Cache uncached members
|
||||
if (message.guild && !message.member) await message.guild.fetchMember(message.author);
|
||||
|
||||
const cmd = this.client.commands.get(command) || this.client.commands.get(this.client.aliases.get(command));
|
||||
if (!cmd) return;
|
||||
|
||||
if (cmd && cmd.conf.devOnly && this.client.util.isDeveloper(message.author.id) !== true) {
|
||||
return message.channel.send("devs only!");
|
||||
}
|
||||
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.");
|
||||
}
|
||||
|
||||
|
||||
message.flags = [];
|
||||
while (args[0] &&args[0][0] === "-") {
|
||||
message.flags.push(args.shift().slice(1));
|
||||
}
|
||||
|
||||
message.util = this.client.messageUtil;
|
||||
|
||||
cmd.run(message, args, data);
|
||||
this.client.logger.cmd(`Command ran: ${message.content}`);
|
||||
|
||||
// TODO: Command caching if it"s worth it
|
||||
}
|
||||
};
|
10
bot/events/ready.js
Normal file
10
bot/events/ready.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
module.exports = class {
|
||||
constructor (client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async run () {
|
||||
await this.client.wait(1000);
|
||||
this.client.logger.ready(`Connected to Discord as ${this.client.user.tag}`);
|
||||
}
|
||||
};
|
46
bot/index.js
Normal file
46
bot/index.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Check that the runtime is up to date
|
||||
if (Number(process.version.slice(1).split(".")[0]) < 12) {
|
||||
console.error(`Node v12.0.0 or higher is required. You have Node ${process.version}. Please update Node on your system.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Load up the discord.js library
|
||||
const { Collection, Client } = require("discord.js");
|
||||
|
||||
// Our custom client, extends the standard Discord client with things we will need.
|
||||
class Custom extends Client {
|
||||
constructor (options) {
|
||||
super(options);
|
||||
|
||||
this.path = __dirname;
|
||||
this.dev = true;
|
||||
this.config = require("../config.json");
|
||||
this.logger = require("./util/logger");
|
||||
this.util = new (require("./util/util"))(this);
|
||||
this.messageUtil = new (require("./util/messageUtil"))(this);
|
||||
|
||||
// Create collections to store loaded commands and aliases in
|
||||
this.commands = new Collection();
|
||||
this.aliases = new Collection();
|
||||
|
||||
const handlers = require("./util/handlers");
|
||||
this.commandHandler = new handlers.CommandHandler(this);
|
||||
this.eventHandler = new handlers.EventHandler(this);
|
||||
|
||||
// Basically just an async shortcut to using a setTimeout. Nothing fancy!
|
||||
this.wait = require("util").promisify(setTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize client
|
||||
const client = new Custom();
|
||||
|
||||
client.commandHandler.loadAll();
|
||||
client.eventHandler.loadAll();
|
||||
|
||||
if (client.dev === true) {
|
||||
client.logger.warn("Development mode is on.");
|
||||
client.login(client.config.devtoken);
|
||||
} else {
|
||||
client.login(client.config.token);
|
||||
}
|
13
bot/shardLauncher.js
Normal file
13
bot/shardLauncher.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
const discord = require("discord.js");
|
||||
const config = require("../config.json");
|
||||
|
||||
const manager = new discord.ShardingManager("./index.js", {
|
||||
totalShards: "auto",
|
||||
token: config.token
|
||||
});
|
||||
|
||||
manager.on("shardCreate", (shard) => {
|
||||
console.log("Shard " + shard.id + " launched");
|
||||
});
|
||||
|
||||
manager.spawn();
|
94
bot/util/handlers.js
Normal file
94
bot/util/handlers.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
const fs = require("fs");
|
||||
|
||||
class CommandHandler {
|
||||
constructor (client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
load (name, category) {
|
||||
try {
|
||||
const path = this.client.path + "/commands/" + category + "/" + name + ".js";
|
||||
const props = new (require(path))(this.client);
|
||||
|
||||
this.client.logger.debug(`Loading command ${category}/${name}`);
|
||||
|
||||
props.help.name = name;
|
||||
props.help.category = category;
|
||||
|
||||
if (props.init) {
|
||||
props.init(this.client);
|
||||
}
|
||||
|
||||
this.client.commands.set(props.help.name, props);
|
||||
|
||||
props.conf.aliases.forEach(alias => {
|
||||
this.client.aliases.set(alias, props.help.name);
|
||||
});
|
||||
|
||||
return;
|
||||
} catch (err) {
|
||||
return `Failed to load command ${name}: ${err}`;
|
||||
}
|
||||
}
|
||||
|
||||
unload (name) {
|
||||
|
||||
}
|
||||
|
||||
loadAll () {
|
||||
const commandDirectories = fs.readdirSync("./commands/");
|
||||
this.client.logger.debug(`Found ${commandDirectories.length} command directories.`);
|
||||
commandDirectories.forEach((dir) => {
|
||||
const commandFiles = fs.readdirSync("./commands/" + dir + "/");
|
||||
commandFiles.filter((cmd) => cmd.split(".").pop() === "js").forEach((cmd) => {
|
||||
cmd = cmd.substring(0, cmd.length - 3);
|
||||
const resp = this.load(cmd, dir);
|
||||
if (resp) {
|
||||
this.client.logger.error(resp);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class EventHandler {
|
||||
constructor (client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
load (name) {
|
||||
try {
|
||||
this.client.logger.debug(`Loading event ${name}`);
|
||||
|
||||
const path = this.client.path + "/events/" + name + ".js";
|
||||
const event = new (require(path))(this.client);
|
||||
this.client.on(name, (...args) => event.run(...args));
|
||||
delete require.cache[require.resolve(path)];
|
||||
|
||||
return;
|
||||
} catch (err) {
|
||||
return `Failed to load event ${name}: ${err}`;
|
||||
}
|
||||
}
|
||||
|
||||
unload (name) {
|
||||
|
||||
}
|
||||
|
||||
loadAll () {
|
||||
const eventFiles = fs.readdirSync(this.client.path + "/events");
|
||||
eventFiles.forEach(file => {
|
||||
const name = file.split(".")[0];
|
||||
const resp = this.load(name);
|
||||
|
||||
if (resp) {
|
||||
this.client.logger.error(resp);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CommandHandler: CommandHandler,
|
||||
EventHandler: EventHandler
|
||||
};
|
54
bot/util/logger.js
Normal file
54
bot/util/logger.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
const { createLogger, format, transports, addColors } = require("winston");
|
||||
const { combine, timestamp, printf, colorize } = format;
|
||||
|
||||
const fmt = printf(({ level, message, timestamp }) => {
|
||||
return `${timestamp} - ${level}: ${message}`;
|
||||
});
|
||||
|
||||
const customLevels = {
|
||||
levels: {
|
||||
debug: 0,
|
||||
cmd: 1,
|
||||
info: 2,
|
||||
ready: 3,
|
||||
warn: 4,
|
||||
error: 5
|
||||
},
|
||||
|
||||
colours: {
|
||||
debug: "magenta",
|
||||
cmd: "white",
|
||||
info: "cyan",
|
||||
ready: "green",
|
||||
warn: "yellow",
|
||||
error: "red"
|
||||
}
|
||||
};
|
||||
|
||||
const logger = createLogger({
|
||||
levels: customLevels.levels,
|
||||
level: "error",
|
||||
format: combine(
|
||||
timestamp({
|
||||
format: "YYYY-MM-DD hh:mm:ss"
|
||||
}),
|
||||
fmt
|
||||
),
|
||||
|
||||
transports: [
|
||||
new transports.Console({
|
||||
level: "error",
|
||||
format: combine(
|
||||
timestamp({
|
||||
format: "YYYY-MM-DD hh:mm:ss"
|
||||
}),
|
||||
colorize(),
|
||||
fmt
|
||||
)
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
addColors(customLevels.colours);
|
||||
|
||||
module.exports = logger;
|
8
bot/util/messageUtil.js
Normal file
8
bot/util/messageUtil.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
class MessageUtil {
|
||||
constructor (client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = MessageUtil;
|
35
bot/util/util.js
Normal file
35
bot/util/util.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
class Util {
|
||||
constructor (client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
isDeveloper (userID) {
|
||||
let isDev = false;
|
||||
const developers = this.client.config.ownerIDs;
|
||||
|
||||
developers.forEach(devID => {
|
||||
if (devID === userID) {
|
||||
isDev = true;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(isDev);
|
||||
return isDev;
|
||||
}
|
||||
|
||||
async clean (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(this.client.token, "mfa.VkO_2G4Qv3T--NO--lWetW_tjND--TOKEN--QFTm6YGtzq9PH--4U--tG0");
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Util;
|
Loading…
Add table
Add a link
Reference in a new issue