var fs = require('fs'), path = require('path'), RDB = require('./redis.js'), async = require('async'), winston = require('winston'), plugins = { libraries: {}, loadedHooks: {}, init: function() { if (this.initialized) return; if (global.env === 'development') winston.info('[plugins] Initializing plugins system'); var _self = this; // Read the list of activated plugins and require their libraries async.waterfall([ function(next) { RDB.smembers('plugins:active', next); }, function(plugins, next) { if (plugins && Array.isArray(plugins) && plugins.length > 0) { async.each(plugins, function(plugin, next) { // TODO: Update this check to also check node_modules var pluginPath = path.join(__dirname, '../plugins/', plugin), modulePath = path.join(__dirname, '../node_modules/', plugin); if (fs.existsSync(pluginPath)) _self.loadPlugin(pluginPath, next); else if (fs.existsSync(modulePath)) _self.loadPlugin(modulePath, next); else { if (global.env === 'development') winston.warn('[plugins] Plugin \'' + plugin + '\' not found'); next(); // Ignore this plugin silently } }, next); } else next(); }, function(next) { if (global.env === 'development') winston.info('[plugins] Sorting hooks to fire in priority sequence'); Object.keys(_self.loadedHooks).forEach(function(hook) { var hooks = _self.loadedHooks[hook]; hooks = hooks.sort(function(a, b) { return a[3] - b[3]; }); }); next(); } ], function(err) { if (err) { if (global.env === 'development') winston.info('[plugins] NodeBB encountered a problem while loading plugins', err.message); return; } if (global.env === 'development') winston.info('[plugins] Plugins OK'); }); }, initialized: false, loadPlugin: function(pluginPath, callback) { var _self = this; fs.readFile(path.join(pluginPath, 'plugin.json'), function(err, data) { if (err) return callback(err); var pluginData = JSON.parse(data); _self.libraries[pluginData.id] = require(path.join(pluginPath, pluginData.library)); if (pluginData.hooks) { for(var x=0,numHooks=pluginData.hooks.length;x