Permalink
Browse files

findUser, findMember, gracefulExit

  • Loading branch information...
1 parent 47b032f commit 25e1c0f3c479ecd9e6b8998ae78c9ffb9296c242 @brussell98 committed Dec 4, 2016
Showing with 140 additions and 24 deletions.
  1. +20 −1 .eslintrc
  2. +5 −0 examples/test/commands/GeneralCommands.js
  3. +20 −0 examples/test/commands/general/Resolve.js
  4. +1 −1 lib/Base/AbstractCommand.js
  5. +86 −18 lib/Bot.js
  6. +8 −4 package.json
View
@@ -21,7 +21,26 @@
"space-before-function-paren": ["warn", "never"],
"arrow-spacing": 1,
"comma-spacing": ["warn", { "before": false, "after": true }],
- "indent": ["error", "tab", { "SwitchCase": 1 }]
+ "indent": ["error", "tab", { "SwitchCase": 1 }],
+ "require-jsdoc": ["warn", { "require": { "MethodDefinition": true, "ClassDeclaration": true } }],
+ "valid-jsdoc": ["warn", {
+ "prefer": {
+ "arg": "param",
+ "argument": "param",
+ "constructor": "class",
+ "return": "returns",
+ "virtual": "abstract"
+ },
+ "preferType": {
+ "boolean": "Boolean",
+ "number": "Number",
+ "object": "Object",
+ "string": "String"
+ },
+ "requireReturn": false,
+ "requireParamDescription": true,
+ "requireReturnDescription": true
+ }]
},
extends: "eslint:recommended"
}
@@ -38,6 +38,11 @@ class GeneralCommands extends AbstractCommandPlugin {
});
}
+ destroy() {
+ super.destroy();
+ return Promise.all(Object.keys(this.commands).map(c => this.commands[c].destroy()));
+ }
+
handle(message) {
if (message.content.startsWith('m.')) {
let command = message.content.substr(2);
@@ -0,0 +1,20 @@
+var AbstractCommand = require('../../../../lib/base/AbstractCommand');
+
+class ResolveCommand extends AbstractCommand {
+ constructor() {
+ super();
+ }
+
+ get name() {
+ return 'resolve';
+ }
+
+ handle(message, args) {
+ let member = this.parent.bot.findMember(args, message.channel.guild.members);
+ if (member === null)
+ return this.sendMessage(message, "I couldn't find anyone with that name in this guild");
+ this.sendMessage(message, 'I found a member with the name ' + (member.nick || member.user.username));
+ }
+}
+
+module.exports = ResolveCommand;
@@ -38,7 +38,7 @@ class AbstractCommand {
this._sendMessage(channel, _content, options);
i += 2000;
options.file = undefined;
- } // TODO: Make sure JS doesn't screw this up by changing the variables in _sendMessage()
+ }
}).catch(error => this.parent.logger.warn(error)); // TODO
}
View
@@ -12,23 +12,30 @@ try {
/**
* Manages the connection to Discord and interaction between plugins
- * @extends {@link http://eris.tachibana.erendale.abal.moe/Eris/docs/Client|Eris.Client}
- * @example <caption>Create a new instance of Mirai</caption>
- * const Mirai = require('mirai-bot-discord');
- * var config = require('./config.json');
- * var mirai = new Mirai(config);
+ * @extends Eris.Client
+ * @see {@link https://abal.moe/Eris/docs/Client|Eris.Client}
*/
class Bot extends Eris.Client {
- constructor(config = {}, rLogger, rChatHandler) {
- super(config.token, config.eris);
+ /**
+ * Creates a new instance of Mirai
+ * @param {Object} [options] An object defining the configuration for Mirai
+ * @param {Class} [rLogger] A replacement Logger. Must implement `log` `info` `debug` `warn` and `error`
+ * @param {Class} [rChatHandler] A replacement ChatHandler. Must implement `run` and `stop`
+ * @example <caption>Create a new instance of Mirai</caption>
+ * const Mirai = require('mirai-bot-discord');
+ * var config = require('./config.json');
+ * var mirai = new Mirai(config);
+ */
+ constructor(options = {}, rLogger, rChatHandler) {
+ super(options.token, options.eris);
- this.carbonBotsKey = config.carbonBotsKey;
- this.discordBotsKey = config.discordBotsKey;
+ this.carbonBotsKey = options.carbonBotsKey;
+ this.discordBotsKey = options.discordBotsKey;
- this.logger = rLogger || new Logger(config.logger);
- this.chatHandler = rChatHandler || new ChatHandler(this, config.chatHandler);
- this.blacklistedGuilds = config.blacklistedGuilds || [];
- this.blacklistedUsers = config.blacklistedUsers || [];
+ this.logger = rLogger || new Logger(options.logger);
+ this.chatHandler = rChatHandler || new ChatHandler(this, options.chatHandler);
+ this.blacklistedGuilds = options.blacklistedGuilds || [];
+ this.blacklistedUsers = options.blacklistedUsers || [];
this.commandPlugins = [];
this.eventPlugins = [];
this.middleware = [];
@@ -67,14 +74,26 @@ class Bot extends Eris.Client {
}
});
}
+
+ if (options.gracefulExit === true) {
+ process.on('SIGINT', () => {
+ let destroyAll = this.commandPlugins.map(p => p.destroy()).concat( this.eventPlugins.map(p => p.destroy()), this.middleware.map(m => m.destroy()))
+ this.disconnect({reconnect: false});
+ Promise.all(destroyAll).then(() => process.exit(0)).catch(error => {
+ this.logger.error(error);
+ process.exit(1);
+ });
+ });
+ }
}
/**
- * @param {Function} plugin The plugin to load. Must have a load() method which is passed <code>this</code>.
+ * @param {Function} plugin The plugin to load. Must have a `load` method which is passed `this`
+ * @see {@link AbstractCommandPlugin}
* @example <caption>Loading a Command Plugin</caption>
* var funCommands = new FunCommandsPlugin();
* mirai.loadCommandPlugin(funCommands);
- * @returns {Promise}
+ * @returns {Promise} The result of `plugin.load`
*/
loadCommandPlugin(plugin) {
return plugin.load(this).then(() => {
@@ -103,7 +122,7 @@ class Bot extends Eris.Client {
}
/**
- * @param {Function} plugin The plugin to load. Must have a load() method which is passed <code>this</code>.
+ * @param {Function} plugin The plugin to load. Must have a `load` method which is passed `this`
* @returns {Promise}
*/
loadEventPlugin(plugin) {
@@ -158,6 +177,12 @@ class Bot extends Eris.Client {
});
}
+ /**
+ * Updates information on carbonitex.net
+ * @param {String} [key] Carbon API key
+ * @returns {Promise} The axios request
+ * @see {@link https://github.com/mzabriskie/axios/blob/master/README.md#response-schema|Axios response}
+ */
updateCarbon(key) {
return axios.post('https://www.carbonitex.net/discord/data/botdata.php', {
key: key || this.carbonBotsKey,
@@ -166,23 +191,34 @@ class Bot extends Eris.Client {
this.logger.debug('Sent servercount:', this.guilds.size, 'to carbonitex.net. Response:', response.status);
}).catch(error => {
if (error.response)
- return this.logger.warn('Error response status', error.response.status, 'from carbonitex.net. Data:', error.response.data);
+ return this.logger.warn('Error: Response status', error.response.status, 'from carbonitex.net. Data:', error.response.data);
this.logger.error('Error during axios request:', error.stack);
});
}
+ /**
+ * Updates information on bots.discord.pw
+ * @param {String} [key] bots.discord.pw API key
+ * @returns {Promise} The axios request
+ * @see {@link https://github.com/mzabriskie/axios/blob/master/README.md#response-schema|Axios response}
+ */
updateDiscordBots(key) {
return axios.post(`https://bots.discord.pw/api/bots/${this.user.id}/stats`, { server_count: this.guilds.size }, {
headers: { 'Authorization': key || this.discordBotsKey }
}).then(response => {
this.logger.debug('Sent server_count:', this.guilds.size, 'to bots.discord.pw. Response:', response.status);
}).catch(error => {
if (error.response)
- return this.logger.warn('Error response status', error.response.status, 'from bots.discord.pw. Data:', error.response.data);
+ return this.logger.warn('Error: Response status', error.response.status, 'from bots.discord.pw. Data:', error.response.data);
this.logger.error('Error during axios request:', error.stack);
});
}
+ /**
+ * Sets the bot's avatar from a url
+ * @param {String} url A direct link to an image
+ * @returns {Promise} Rejects with an error, if there is one. May be a `String` or `Error`
+ */
setAvatar(url) {
return new Promise((resolve, reject) => {
axios.get(url, {
@@ -204,6 +240,38 @@ class Bot extends Eris.Client {
});
});
}
+
+ /**
+ * Resolve a name to a user
+ * @param {String} query The name to match
+ * @returns {User?} The user the was found, or null
+ * @see {@link https://abal.moe/Eris/docs/User|Eris.User}
+ */
+ findUser(query) {
+ query = query.toLowerCase().trim();
+ let result = null;
+ result = this.users.find(user => user.username.toLowerCase() === query);
+ if (!result)
+ result = this.users.find(user => user.username.toLowerCase().includes(query));
+ return result || null;
+ }
+
+ /**
+ * Resolve a name to a guild member
+ * @param {String} query The name to match
+ * @param {Collection} members The Collection of guild members
+ * @returns {Member?} The member the was found, or null
+ * @see {@link https://abal.moe/Eris/docs/Member|Eris.Member}
+ */
+ findMember(query, members) {
+ query = query.toLowerCase().trim();
+ let result = null;
+ result = members.find(member => member.user.username.toLowerCase() === query);
+ if (!result) result = members.find(member => member.nick && member.nick.toLowerCase() === query);
+ if (!result) result = members.find(member => member.user.username.toLowerCase().includes(query));
+ if (!result) result = members.find(member => member.nick && member.nick.toLowerCase().includes(query));
+ return result || null;
+ }
}
module.exports = Bot;
View
@@ -1,15 +1,19 @@
{
- "name": "mirai-bot-discord",
- "version": "4.0.0-alpha",
- "description": "A simple Discord bot base",
+ "name": "mirai-bot-core",
+ "version": "4.0.0-beta",
+ "description": "A Discord bot core allowing easy plugging in of modules",
"author": "brussell98",
"main": "index.js",
"keywords": [
"discord",
"bot",
+ "core",
+ "framework",
"eris",
"es6",
"plugins",
+ "middleware",
+ "modules",
"mirai"
],
"homepage": "https://github.com/brussell98/Mirai#readme",
@@ -29,7 +33,7 @@
},
"license": "MIT",
"dependencies": {
- "axios": "^0.15.2",
+ "axios": "^0.15.3",
"chalk": "^1.1.3",
"eris": "abalabahaha/eris#dev"
},

0 comments on commit 25e1c0f

Please sign in to comment.