Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Settings - no tracking yet #66

Merged
merged 7 commits into from
Mar 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"bluebird": "^3.4.7",
"decache": "^4.1.0",
"discord.js": "^11.0.0",
"erlpack": "github:hammerandchisel/erlpack#master",
"json-fetch-cache": "0.0.5",
"mysql2": "^1.1.2",
"node-md-config": "^2.0.1",
Expand Down
3 changes: 2 additions & 1 deletion pm2.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"MYSQL_PASSWORD":"password",
"MYSQL_DB":"genesis",
"LOG_LEVEL": "ERROR",
"WORLDSTATE_TIMEOUT": 60000
"WORLDSTATE_TIMEOUT": 60000,
"INVITE_URL" : "https://github.com/Warframe-Community-Developers/genesis"
}
}
]
Expand Down
26 changes: 25 additions & 1 deletion src/Command.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Command {
* Command regex for calling the command
* @type {RegExp}
*/
this.regex = new RegExp(`^${bot.escapedPrefix}${call}s?$`, 'i');
this.regex = new RegExp(`^${call}s?$`, 'i');
/**
* Help command for documenting the function or purpose of a command.
* @type {string}
Expand Down Expand Up @@ -78,6 +78,30 @@ class Command {
* @type {boolean}
*/
this.ownerOnly = false;

/**
* True if this command is allowed to be disabled.
* @type {Boolean}
*/
this.blacklistable = true;

/**
* True if this command requires authorization to be executed
* @type {Boolean}
*/
this.requiresAuth = false;

/**
* True if this command is allowed in direct messages
* @type {Boolean}
*/
this.allowDM = true;

/**
* Message manager for sending and managing messages
* @type {MessageManager}
*/
this.messageManager = bot.messageManager;
}

/**
Expand Down
103 changes: 80 additions & 23 deletions src/CommandHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,20 @@ class CommandHandler {
*/
loadCommands() {
const commandDir = path.join(__dirname, 'commands');
const files = fs.readdirSync(commandDir);
let files = fs.readdirSync(commandDir);

const categories = files.filter(f => f.indexOf('.js') === -1);
files = files.filter(f => f.indexOf('.js') > -1);

categories.forEach((category) => {
files = files.concat(fs.readdirSync(path.join(commandDir, category))
.map(f => path.join(category, f)));
});

if (this.commands.length !== 0) {
this.logger.debug('Decaching commands');
files.forEach((f) => {
decache(`${commandDir}/${f}`);
decache(path.join(commandDir, f));
});
}

Expand All @@ -43,7 +51,7 @@ class CommandHandler {
this.commands = files.map((f) => {
try {
// eslint-disable-next-line import/no-dynamic-require, global-require
const Cmd = require(`${commandDir}/${f}`);
const Cmd = require(path.join(commandDir, f));
if (Object.prototype.toString.call(Cmd) === '[object Function]') {
const command = new Cmd(this.bot);

Expand All @@ -64,33 +72,82 @@ class CommandHandler {
* @param {Message} message Message whose command should be checked and handled
*/
handleCommand(message) {
const content = message.cleanContent;
if (!content.startsWith(this.bot.prefix)) {
return;
}

this.logger.debug(`Handling \`${content}\``);
this.commands.forEach((command) => {
if (command.regex.test(content) && this.checkCanAct(command, message.author)) {
this.logger.debug(`Matched ${command.id}`);
message.react('\u2705').catch(this.logger.error);
command.run(message);
}
});
let content = message.cleanContent;
const botping = `@${this.bot.client.user.username}`;
this.bot.settings.getChannelPrefix(message.channel)
.then((prefix) => {
if (!content.startsWith(prefix) && !content.startsWith(botping)) {
return;
}
if (content.startsWith(prefix)) {
content = content.replace(prefix, '');
}
if (content.startsWith(botping)) {
content = content.replace(new RegExp(`${botping}\\s+`, 'i'), '');
}
const messageWithStrippedContent = message;
messageWithStrippedContent.strippedContent = content;
this.logger.debug(`Handling \`${content}\``);
this.commands.forEach((command) => {
if (command.regex.test(content)) {
this.checkCanAct(command, messageWithStrippedContent)
.then((canAct) => {
if (canAct) {
this.logger.debug(`Matched ${command.id}`);
message.react('\u2705').catch(this.logger.error);
command.run(messageWithStrippedContent);
}
});
}
});
})
.catch(this.logger.error);
}

/**
* Check if the current command being called is able to be performed for the user calling it.
* @param {Command} command command to process to see if it can be called
* @param {User} author caller of the message, the author.
* @param {Message} message Discord message object
* @returns {boolean} Whether or not the ucrrent command can be called by the author
*/
checkCanAct(command, author) {
if (command.ownerOnly && author.id !== this.bot.owner) {
return false;
}
// TODO: Do blacklist checking
return true;
checkCanAct(command, message) {
return new Promise((resolve) => {
if (message.channel.type === 'text') {
if (command.requiresAuth && message.channel.permissionsFor(message.author).hasPermission('MANAGE_ROLES_OR_PERMISSIONS')) {
this.bot.settings
.getChannelPermissionForMember(message.channel, message.author.id, command.id)
.then((userHasPermission) => {
resolve(userHasPermission);
})
.catch(() => {
this.bot.settings
.getChannelPermissionForUserRoles(message.channel,
message.author, command.id)
.then((userHasPermission) => {
resolve(userHasPermission);
});
});
} else {
this.bot.settings
.getChannelPermissionForMember(message.channel, message.author.id, command.id)
.then((userHasPermission) => {
resolve(userHasPermission);
})
.catch(() => {
this.bot.settings
.getChannelPermissionForUserRoles(message.channel,
message.author, command.id)
.then((userHasPermission) => {
resolve(userHasPermission);
});
});
}
} else if (message.channel.type === 'dm' && command.allowDM) {
resolve(true);
} else {
resolve(false);
}
});
}
}

Expand Down
32 changes: 31 additions & 1 deletion src/Tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const carbonToken = process.env.DISCORD_CARBON_TOKEN;
const botsDiscordPwToken = process.env.DISCORD_BOTS_WEB_TOKEN;
const botsDiscordPwUser = process.env.DISCORD_BOTS_WEB_USER;
const updateInterval = process.env.TRACKERS_UPDATE_INTERVAL || 2600000;
const discordListToken = process.env.DISCORD_LIST_TOKEN;

/**
* Describes a tracking service for updating remote sites
Expand All @@ -28,6 +29,9 @@ class Tracker {
if (botsDiscordPwToken && botsDiscordPwUser) {
setInterval(() => this.updateDiscordBotsWeb(this.client.guilds.size), updateInterval);
}
if (discordListToken) {
setInterval(() => this.updateDiscordList(this.client.guilds.size), updateInterval);
}
}

/**
Expand All @@ -50,7 +54,32 @@ class Tracker {
.then((parsedBody) => {
this.logger.debug(parsedBody);
})
.catch(error => this.logger.error(error));
.catch(this.logger.error);
}
}

/**
* Updates discordlist.net if the corresponding token is provided
* @param {number} guildsLen number of guilds that this bot is present on
*/
updateDiscordList(guildsLen) {
if (discordListToken) {
this.logger.debug('Updating DiscordList');
this.logger.debug(`${this.client.user.username} is on ${guildsLen} servers`);

const requestBody = {
url: 'https://bots.discordlist.net/api',
body: {
token: discordListToken,
servers: guildsLen,
},
json: true,
};
request(requestBody)
.then((parsedBody) => {
this.logger.debug(parsedBody);
})
.catch(this.logger.error);
}
}

Expand Down Expand Up @@ -91,6 +120,7 @@ class Tracker {
updateAll(guildsLen) {
this.updateCarbonitex(guildsLen);
this.updateDiscordBotsWeb(guildsLen);
this.updateDiscordList(guildsLen);
}
}

Expand Down
20 changes: 12 additions & 8 deletions src/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const md = require('node-md-config');
const WorldStateCache = require('./WorldStateCache.js');
const Database = require('./settings/Database.js');
const Tracker = require('./Tracker.js');
const MessageManager = require('./settings/MessageManager.js');

/**
* A collection of strings that are used by the parser to produce markdown-formatted text
Expand Down Expand Up @@ -112,12 +113,6 @@ class Genesis {
*/
this.owner = owner;

/**
* The status message to use for the bot
* @type {string}
*/
this.statusMessage = `${prefix}help for help (${this.shardId + 1}/${this.shardCount})`;

/**
* Persistent storage for settings
* @type {Database}
Expand Down Expand Up @@ -148,8 +143,16 @@ class Genesis {
this.worldStates[platform] = new WorldStateCache(platform, worldStateTimeout);
});

/**
* The languages that are useable for the bot
* @type {Array.<string>}
*/
this.languages = ['en-us'];

this.tracker = new Tracker(this.logger, this.client, { shardId, shardCount });

this.messageManager = new MessageManager(this);

this.commandHandler.loadCommands();

this.setupHandlers();
Expand Down Expand Up @@ -178,7 +181,7 @@ class Genesis {
* Creates the database schema and logs in the bot to Discord
*/
start() {
this.settings.createSchema().then(() => {
this.settings.createSchema(this.client).then(() => {
this.logger.debug('Schema created');
return this.client.login(this.token);
}).then((t) => {
Expand All @@ -196,7 +199,8 @@ class Genesis {
onReady() {
this.logger.debug(`${this.client.user.username} ready!`);
this.logger.debug(`Bot: ${this.client.user.username}#${this.client.user.discriminator}`);
this.client.user.setGame(this.statusMessage);
this.client.user.setGame(`@${this.client.user.username} help (${this.shardId + 1}/${this.shardCount})`);
this.settings.ensureData(this.client);
this.readyToExecute = true;
}

Expand Down
22 changes: 10 additions & 12 deletions src/commands/Bug.js → src/commands/Core/Bug.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const Command = require('../Command.js');
const Command = require('../../Command.js');

/**
* Send a bug report to owner
Expand All @@ -12,7 +12,7 @@ class BugReport extends Command {
*/
constructor(bot) {
super(bot, 'core.bug', 'bug', 'Send a bug report to the bot owner');
this.regex = new RegExp(`^${this.bot.escapedPrefix}${this.call}\\s*(.*)?`, 'i');
this.regex = new RegExp(`^${this.call}\\s*(.*)?`, 'i');
this.usages = [
{
description: 'Send a bug report to bot owner',
Expand All @@ -37,10 +37,10 @@ class BugReport extends Command {
* or perform an action based on parameters.
*/
run(message) {
const bugReport = message.cleanContent.match(this.regex)[1];
const bugReport = message.strippedContent.match(this.regex)[1];

if (this.bot.owner) {
if(bugReport) {
if (bugReport) {
const params = bugReport.split('|');
const embed = {
author: {
Expand Down Expand Up @@ -68,20 +68,18 @@ class BugReport extends Command {
};
}
}

this.bot.client.users.get(this.bot.owner)
.sendEmbed(embed)
.then(() => message.reply('Bug report sent.'))
.catch(this.logger.error);
this.messageManager.sendDirectEmbedToOwner(embed);
this.messageManager.reply(message, 'Bug report sent.', true, true);
} else {
message.channel.sendEmbed({
const embed = {
author: {
icon_url: message.author.avatarURL,
name: `${message.author.username}#${message.author.discriminator}`,
},
title: `Bug Report | ${message.author}`,
fields: [{name: '_ _', value:'Need to provide a bug report, see `/help` for syntax.'}],
}).catch(this.logger.error)
fields: [{ name: '_ _', value: 'Need to provide a bug report, see `/help` for syntax.' }],
};
this.messageManager.embed(message, embed, true, false);
}
}
}
Expand Down
Loading