Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
prepping for wk 4 release, taking out .env file
  • Loading branch information
Mark Langenhorst committed Jan 22, 2018
commit 839673983c79af77db2296dc5210629c5b64919d
1 change: 1 addition & 0 deletions Max-Bot
Submodule Max-Bot added at a87560
13 changes: 13 additions & 0 deletions bot/baseCommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class BaseCommand {
constructor(command, example, title, desc, action, resType = 'reply', showWithHelp = true, allowInDM = false) {
this.command = command;
this.example = example;
this.title = title;
this.desc = desc;
this.showWithHelp = showWithHelp;
this.allowInDM = allowInDM;
this.resType = resType;
this.action = action;
}
}
module.exports = BaseCommand;
64 changes: 64 additions & 0 deletions bot/baseController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const util = require('apex-util');

class BaseController {
constructor(message) {
// Add middleware to saved message
this.message = BaseController.messageMiddleware(message);
this.commands = [];
}

// Add extra information to message object
static messageMiddleware(message) {
// Creates an empty object container
const messageContainer = {};
// Tokenizes the message by space characters, adds to container
messageContainer.parsed = message.content.split(' ');
// Adds message object to container
return Object.assign(message, messageContainer);
}

onSuccess(commandResponse, command) {
if (commandResponse !== null) {
// Determine how to respond to message
if (command.resType === 'reply') {
return this.message.reply(commandResponse);
} else if (command.resType === 'dm') {
return this.message.author.send(commandResponse);
}
}
// Fail safe
return false;
}

onError(errorMessage = 'I Broke... Beep...Boop...Beep') {
return this.message.reply(errorMessage);
}

// Execute the command's functionality
run() {
// Loop through each command and map to key
util.log('Looping through controller commands', 0);
Object.keys(this.commands).map((key) => {
// If command matches message
if (this.message.parsed[0].toLowerCase() === this.commands[key].command.toLowerCase()) {
util.log('Matching command found', this.commands[key].command, 2);

// If user messages the bot a channel-only command
if (!this.commands[key].allowInDM && !this.message.guild) {
return this.onError('Please don\'t use this command directly. Instead use it in a channel on a server. :beers:');
}

// Execute command's action
const commandResponse = this.commands[key].action();
// Handle if command responds or breaks
if (commandResponse) {
this.onSuccess(commandResponse, this.commands[key]);
} else {
this.onError();
}
}
return this.commands[key];
});
}
}
module.exports = BaseController;
42 changes: 14 additions & 28 deletions bot/client.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,32 @@
const Discord = require('discord.js');
const util = require('apex-util');

// If Production server default Debug mode to Production Setting
// If production server, set default debug mode to production setting
if (process.env.NODE_ENV === 'production' && !process.env.DEBUG_MODE) process.env.DEBUG_MODE = 0;

const client = new Discord.Client();

// Pre Load Controllers
const ctrls = require('./controllers')();
// Pre-load controllers
const controllers = require('./controllers')();

// Alert when ready
client.on('ready', () => {
util.log('Bot Online and Ready!', 0);
util.log('Bot Online and Ready', 0);
});

// Listen for messages
client.on('message', (message) => {
// Check for ! Prefix on message to ensure it is a command
// Check for ! prefix on message to ensure it is a command
if (message.content.charAt(0) === '!') {
util.log('!Cmd Message Received', message.content, 0);

const ctrlResponses = [];
util.log('Command message received', message.content, 0);

// Process message against every controller
Object.keys(ctrls).forEach((ctrlKey) => {
if (ctrlKey) {
// initialize the controller
const ctrlInstance = ctrls[ctrlKey]();

// Determine the method names of each controller
const controllerMethodKeys = Object.keys(ctrlInstance);
util.log('Methods found in controller', controllerMethodKeys, 3);

// For each method on each controller
Object.keys(controllerMethodKeys).forEach((controllerMethodKey) => {
const methodName = controllerMethodKeys[controllerMethodKey];
const method = ctrlInstance[methodName];

util.log('Looping Through Each Method within each Controller', method, 4);

// Pass the message to each method of each controller
ctrlResponses.push(method(message));
});
}
Object.keys(controllers).forEach((key) => {
// Instantiate the controller
const controllerInstance = new controllers[key](message);
util.log('Controller instance', controllerInstance, 5);
// Runs commands after constructor is called
controllerInstance.run();
});

// TODO: Improve help message
Expand Down
29 changes: 29 additions & 0 deletions bot/controllerUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class controllerUtils {
constructor() {
// Method to generate random numeric verification code
// Modified to fit style guide from this SO answer:
// https://stackoverflow.com/a/39774334
this.generateCode = (n) => {
// Workaround method for Math.pow() and ** operator
const pow = (base, exp) => {
let result = 1;
for (let i = 0; i < exp; i += 1) {
result *= base;
}
return result;
};
const add = 1;
let max = 12 - add;
let min = 0;
if (n > max) {
return this.generateCode(max) + this.generateCode(n - max);
}
max = pow(10, n + add);
min = max / 10;
const number = Math.floor(Math.random() * (max - (min + 1))) + min;
return ('' + number).substring(add);
};
}
}

module.exports = controllerUtils;
109 changes: 109 additions & 0 deletions bot/controllers/channels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
module.exports = () => {
const util = require('apex-util');

const _run = (message) => {
const ctrls = [
{
cmd: '!channels',
example: '!channels',
title: 'List All Channels',
desc: 'List all Armada Channels',
showWithHelp: true,
posTargetUser: null,
posSecondaryCmd: null,
regexSplitCharacter: null,
allowInDM: false,
resType: 'dm',
action: (message) => {
const channels = [];
message.guild.channels.map((channel) => {
util.log(channel.name);
return channel.name;
});
return 'List of all Armada Channels: \n\n' + channels.join('\n');
},
},
{
cmd: '!notifyTheOthers',
example: '!notifyTheOthers <channel_name>, <message>',
title: 'Add a message to another channel',
desc: 'Type the command, the channel name, and then the message you would like to send.',
showWithHelp: true,
posTargetUser: null,
posSecondaryCmd: null,
regexSplitCharacter: null,
allowInDM: false,
resType: 'reply',
action: (message, ctrl, msg) => {
const channels = msg.parsed[1].split(',');
channels.map((channel) => {
const targetChannel = message.guild.channels.find('name', channel);

if (targetChannel === null) {
return '"' + channel + '" is not a known channel. Try `!channels` to get a list of all Channels (They are case-sensitive)';
}
let fullComment = '';
// Hey, there's a chance comments can have only one word!
if (msg.parsed.length > 3) {
// Add each word to the fullComment variable and send it all together
// Since the first two in the array are not needed, slice them out
msg.parsed.slice(2).forEach((string) => {
fullComment += string + ' ';
});
}
return targetChannel.send(fullComment);
});
return 'The Others have been notified. Godspeed, dear message.';
},
},
];

const onSuccess = (message, res, ctrl) => {
if (res !== null) {
if (ctrl.resType === 'reply') {
return message.reply(res);
} else if (ctrl.resType === 'dm') {
return message.author.send(res);
}
}
// Fail Safe
return false;
};

const onError = message => message.reply('I Broke... Beep...Boop...Beep');

const messageMiddleware = (message) => {
const container = {};
container.parsed = message.content.split(' ');
const msg = Object.assign(message, container);
return msg;
};

ctrls.map((ctrl) => {
util.log('Running through controller', ctrl.cmd, 2);

const msg = messageMiddleware(message);
if (msg.parsed[0].toLowerCase() === ctrl.cmd.toLowerCase()) {
util.log('!!! Matched Ctrl to Cmd !!!', ctrl.cmd, 2);

// Ensure the communication is happening on a server
if (!ctrl.allowInDM) {
if (!message.guild) return onError(message, 'Please don\'t use this command directly. Instead use it in a channel on a server. :beers:');
}

// Do Stuff
const res = ctrl.action(message, ctrl, msg);
if (res) {
onSuccess(message, res, ctrl);
} else {
onError(message, res, ctrl);
}
}
return ctrl;
});
};

return {
run: _run,
};
};
19 changes: 9 additions & 10 deletions bot/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ const fs = require('fs');
const util = require('apex-util');

module.exports = () => {
const ctrls = [];
const controllers = [];
const targetPath = './bot/controllers';
const exts = ['js'];
const validExtensions = ['js'];

// const file = 'roles.js';
// Auto-load controller files
fs.readdirSync(targetPath).forEach((file) => {
// Skip Self Recursive Loading
// Skip self-recursive loading
if (file === 'index.js') return false;

// Split File name on "."
Expand All @@ -18,14 +18,13 @@ module.exports = () => {
const currentExt = splitFile[splitFile.length - 1];

// Check if extension is on approved array
if (exts.includes(currentExt)) {
ctrls.push(require(`./${file}`));
// import/no-dynamic-require
if (validExtensions.includes(currentExt)) {
// Add controller to list
controllers.push(require(`./${file}`));
}

return true;
});

util.log('Return Controllers loaded within the target path of ' + targetPath, ctrls, 3);
return ctrls;
util.log('Controllers found within target path' + targetPath, controllers, 3);
return controllers;
};
Loading