Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const fs = require('fs');
- const path = require('path');
- const chokidar = require('chokidar');
- const utils = require('./utils.js');
- class PluginHandler {
- constructor(dir) {
- this.dir = dir;
- this.plugins = {};
- // handle uncaught exceptions
- process.on('uncaughtException', err => {
- utils.error(err.stack);
- });
- // read files in plugin directory
- let cwd = __dirname.split(/\\/g).join('/');
- let files = this.getFilesSync(dir)
- .map(file => `${cwd}/${file}`);
- // watch directory for changes
- this.watch = chokidar.watch(dir, {persistent:true});
- this.watch.on('ready', () => {
- this.watch.on('error', utils.error);
- this.watch.on('add', path => {this.newPlugin(path)});
- this.watch.on('change', path => {this.reloadPlugin(path)});
- this.watch.on('unlink', path => {this.removePlugin(path)});
- });
- // load plugins
- files.forEach(file => {
- this.addPlugin(file, true);
- });
- utils.log(`Loaded ${files.length} plugins.`);
- }
- /**
- * Give info to corresponding plugin or alias
- * @param {Object} info the message info
- */
- apply(info) {
- if (info.command in this.plugins) {
- let plugin = this.plugins[info.command];
- if ('action' in plugin.module) plugin.module.action(info);
- } else {
- let aliases = Object.values(this.plugins)
- .map(plugin => {
- //console.log('applying plugin:', JSON.stringify(plugin, null, 2));
- return (plugin.module && 'aliases' in plugin.module) ?
- plugin.module.aliases.map(name => {
- return {name: name, plugin: plugin}}) : []
- });
- aliases = {names: aliases, executed: false}
- aliases.names.forEach(names => {
- names.forEach(alias => {
- if (aliases.executed) return;
- if (alias.name === info.command) {
- let plugin = alias.plugin;
- if ('action' in plugin.module) plugin.module.action(info);
- aliases.executed = true;
- }
- });
- });
- }
- }
- /**
- * Read a dir for all of its files synchronously
- * @param {String} dir the directory to scan for files
- * @return {Array} the list of absolute paths to the files
- */
- getFilesSync(dir) {
- const cwd = __dirname.split(/\\/g).join('/');
- const flatten = arr => arr.reduce((acc, val) =>
- acc.concat(Array.isArray(val) ? flatten(val) : val), []);
- return flatten(fs.readdirSync(dir)
- .map(file => fs.statSync(path.join(dir, file)).isDirectory()
- ? this.getFilesSync(path.join(dir, file))
- : path.join(dir, file).replace(/\\/g, '/')))
- }
- /**
- * Get the plugin name of a path
- * @param {String} path the plugin path
- * @return {String} abstracted plugin name
- */
- getName(path) {
- let name = path.split('/')
- .slice(-1)[0]
- .split('.')
- .slice(0,-1)
- .join('.');
- return name;
- }
- /**
- * Get a Plugin by its path
- * @param {String} path the plugin path
- * @return {Object Nullbale} the plugin
- */
- getByPath(path) {
- let name = this.getName(path.replace(/\\/g, '/'));
- return (name in this.plugins) ? this.plugins[name] : null;
- }
- /**
- * Create a new plugin place-holder
- * @param {String} path the path to load the plugin
- * @param {Boolean} quiet whether or not to print action
- */
- newPlugin(path, quiet) {
- if (!path.endsWith('.js')) return;
- let plugin = {
- name: this.getName(path),
- path: path.startsWith('./') ? path.substring(2) : path
- };
- if (!plugin.path.startsWith(__dirname.split('\\')[0]))
- plugin.path = __dirname.split('\\')
- .concat(
- plugin.path
- .split(plugin.path.indexOf('\\') > -1 ? '\\' : '/')
- ).join('/');
- this.plugins[plugin.name] = plugin;
- if (!quiet) utils.log(`Created plugin [${plugin.name}]`);
- return plugin;
- }
- /**
- * Load the action through the plugin place-holder
- * @param {String} path the path of the plugin
- * @param {Boolean} quiet whether or not to print action
- */
- addPlugin(path, quiet) {
- let plugin = this.newPlugin(path, quiet);
- if (!plugin) return;
- if (!quiet) utils.log(`Adding plugin [${plugin.name}]`);
- this.plugins[plugin.name].module = require(plugin.path)
- }
- /**
- * Remove the plugin from the handlers
- * @param {String} path the path of the plugin
- * @param {Boolean} quiet whether or not to print action
- */
- removePlugin(path, quiet) {
- let plugin = this.getByPath(path);
- if (!plugin) return;
- if (plugin.name in this.plugins) {
- if (!quiet) utils.log(`Removing plugin [${plugin.name}]`);
- delete require.cache[require.resolve(plugin.path)];
- delete this.plugins[plugin.name];
- plugin = undefined;
- }
- }
- /**
- * Reload action of plugin through place-holder
- * @param {String} path the path to load the plugin
- * @param {Boolean} quiet whether or not to print action
- */
- reloadPlugin(path, quiet) {
- let plugin = this.getByPath(path);
- if (!plugin) return;
- if (!quiet)
- utils.log(`Reloading plugin [${plugin.name}]`);
- delete require.cache[require.resolve(plugin.path)];
- plugin.module = require(plugin.path);
- }
- };
- module.exports = PluginHandler;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement