Skip to content

Commit

Permalink
feat(modules): add modules for message middlware
Browse files Browse the repository at this point in the history
  • Loading branch information
dsevillamartin committed Apr 4, 2017
1 parent 6dcd12c commit 46f2407
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 20 deletions.
59 changes: 39 additions & 20 deletions lib/Discord/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Client extends DiscordClient {
super(opts, ...args);

this.commands = new Discord.Collection();
this.middleware = new Discord.Collection();
this.aliases = new Discord.Collection();

this.prefix = opts.prefix;
Expand Down Expand Up @@ -56,6 +57,34 @@ class Client extends DiscordClient {
});
}

loadModules(cwd) {
fs.readdir(cwd, (err, files) => {
if (err) {
this.emit('error', err);
return this;
}

if (!files.length) {
Log.info(`Module | No Modules Loaded.`);
return this;
}

files.forEach(f => {
try {
const module = new (require(`./Modules/${f}`))(this);
const name = module.constructor.name.replace('Module', '');

Log.info(`Module | Loading ${name}. 👌`);

this.middleware.set(name, module);
} catch (error) {
this.emit('error', `Module | ${f}`, error);
}
});
return this;
});
}

reloadCommand(command) {
return new Promise((resolve, reject) => {
try {
Expand Down Expand Up @@ -88,36 +117,26 @@ class Client extends DiscordClient {
}

runCommand(msg) {
if (msg.author.equals(this.user) || msg.author.bot) return;
let channelConf = ChannelConfig.FindByChannel(msg.channel.id) || {};
let prefix = channelConf.prefix || Math.random();
if (!msg.content.startsWith(this.user.toString()) && !msg.content.startsWith(prefix) && !msg.content.startsWith(this.prefix)) return false;

let content = (msg.content.startsWith(prefix) && msg.content.replace(prefix, '')) || (msg.content.startsWith(this.user.toString()) && msg.content.replace(`${this.user.toString()} `, '')) || (msg.content.startsWith(this.prefix) && msg.content.replace(this.prefix, '')) || msg.content;
let command = content.split(' ')[0].toLowerCase();
let args = content.split(' ').slice(1);
let perms = this.permissions(msg);

let cmd;

if (this.commands.has(command)) {
cmd = this.commands.get(command);
} else if (this.aliases.has(command)) {
cmd = this.commands.get(this.aliases.get(command));
}
let middleware = this.middleware.array().sort((a, b) => b.priority - a.priority);
let i = 0;

if (cmd) {
this.emit('runCommand', msg);
if (perms < cmd.conf.permLevel) return cmd.commandError(msg, `Insufficient permissions! Must be **${cmd._permLevelToWord(cmd.conf.permLevel)}** or higher`);
const next = (err) => {
let currentMiddleware = middleware[i] || middleware[i - 1];
let nextMiddleware = middleware[i++];
if (err) return msg.channel.sendMessage([`❌ An unexpected error occurred when trying to run middleware \`${currentMiddleware.constructor.name}\``, `\`${err}\``]);
if (nextMiddleware) nextMiddleware.run(msg, args, next, command);
};

try {
let commandRun = cmd.run(msg, args);
if (commandRun && commandRun.catch) {
commandRun.catch(e => this.commandError(msg, cmd, e));
}
} catch (e) {
this.commandError(msg, cmd, e);
}
}
next();

return this;
}
Expand Down
67 changes: 67 additions & 0 deletions lib/Discord/Module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const Discord = require('discord.js');

/**
* Discord bot's middleware, or module
*/
class Module {
/**
* @param {Client} bot - discord bot
*/
constructor(bot) {
this.bot = bot;
this._path = Log._path;
this.embed = Discord.RichEmbed;
}

/**
* Middleware's priority
*/
get priority() {
return 0;
}

/**
* Init module
*/
init() {
// eslint pls
}

/**
* Bot's message middleware function
* @param {Message} msg - the message
* @param {string[]} args - message split by spaces
* @param {function} next - next middleware pls <3
*/
run() {
throw new Error(`No middleware method was set up in module ${this.constructor.name}`);
}

/**
* Function to shorten sending error messages
* @param {Message} msg - message sent by user (for channel)
* @param {string} str - error message to send user
*/
moduleError(msg, str) {
return msg.channel.sendMessage(`❌ ${str}`);
}

/**
* Convert normal text to an embed object
* @param {string} [title = 'Auto Generated Response'] - embed title
* @param {string|string[]} text - embed description, joined with newline if array
* @param {color} [color = '#84F139'] - embed color
* @return {RichEmbed}
*/
textToEmbed(title = 'Auto Generated Response', text, color = '#84F139') {
if (Array.isArray(text)) text = text.join('\n');
return new this.embed()
.setColor(color)
.setTitle(title)
.setDescription(text)
.setFooter(this.bot.user.username, this.bot.user.avatarURL);
}
}


module.exports = Module;
34 changes: 34 additions & 0 deletions lib/Discord/Modules/RunCommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const Module = require('../Module');

class RunCommandModule extends Module {
get priority() {
return 10;
}

run(msg, args, next, command) {
let bot = this.bot;
let perms = bot.permissions(msg);
let cmd;

if (bot.commands.has(command)) {
cmd = bot.commands.get(command);
} else if (bot.aliases.has(command)) {
cmd = bot.commands.get(bot.aliases.get(command));
} else {
return next();
}

if (perms < cmd.conf.permLevel) return cmd.commandError(msg, `Insufficient permissions! Must be **${cmd._permLevelToWord(cmd.conf.permLevel)}** or higher`);

try {
let commandRun = cmd.run(msg, args);
if (commandRun && commandRun.catch) {
commandRun.catch(e => bot.commandError(msg, cmd, e));
}
} catch (e) {
bot.commandError(msg, cmd, e);
}
}
}

module.exports = RunCommandModule;
1 change: 1 addition & 0 deletions lib/Discord/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ bot.on('message', (msg) => {
bot.on('runCommand', Log.message);

bot.loadCommands(path.resolve(__dirname, 'Commands'));
bot.loadModules(path.resolve(__dirname, 'Modules'));

// === LOGIN ===
Log.info(`Bot | Logging in with prefix ${bot.prefix}...`);
Expand Down

0 comments on commit 46f2407

Please sign in to comment.