kara
Version:
A third generation EX-400 android
122 lines (98 loc) • 3.6 kB
JavaScript
var fs = require("fs"),
path = require("path"),
EX400 = require("ex-400"),
redis = require("redis");
var Kara = module.exports = function Kara(config) {
EX400.Core.call(this, config || this._loadConfig());
this.config.plugins = this.config.plugins || {};
this.config.plugins.loadPath = this.config.plugins.loadPath || "./plugins";
this.plugins = {};
this.config.redis = this.config.redis || {};
this.config.redis.lib = this.config.redis.lib || redis;
};
Kara.prototype = Object.create(EX400.Core.prototype, {constructor: {value: Kara}});
// properties
Object.defineProperty(Kara.prototype, "redis", {
get: function getRedis() {
return this._redis || (this._redis = this._redisConnect());
},
});
// public
Kara.prototype.loadPlugin = function loadPlugin(name) {
if (name in this.plugins) { throw new Error("Plugin already loaded: " + name) }
var pluginPath = this._pluginPath(name),
pluginInstance = new (require(pluginPath))(this);
this.plugins[name] = {
enabled: false,
filename: pluginPath,
exports: pluginInstance,
};
return pluginInstance;
};
Kara.prototype.unloadPlugin = function unloadPlugin(name) {
if (!(name in this.plugins)) { throw new Error("Cannot enable unknown plugin: " + name); }
var cachePath = path.resolve(__dirname, this._pluginPath(name));
delete require.cache[cachePath];
delete this.plugins[name];
};
Kara.prototype.enablePlugin = function enablePlugin(name) {
if (!(name in this.plugins)) { throw new Error("Cannot enable unknown plugin: " + name) }
if (this.plugins[name].enabled === true) { return }
this.plugins[name].exports.enable();
this.plugins[name].enabled = true;
};
Kara.prototype.disablePlugin = function disablePlugin(name) {
if (!(name in this.plugins)) { throw new Error("Cannot disable unknown plugin: " + name) }
if (this.plugins[name].enabled === false) { return }
this.plugins[name].exports.disable();
this.plugins[name].enabled = false;
};
// private
Kara.prototype._redisConnect = function _redisConnect() {
var client = this.config.redis.lib.createClient(
this.config.redis.port,
this.config.redis.host,
{parser: "hiredis"}
);
client.on("error", this._onRedisError.bind(this));
client.on("connect", this._onRedisConnect.bind(this));
client.on("end", this._onRedisDisconnect.bind(this));
return client;
};
Kara.prototype._loadConfig = function _loadConfig() {
var configPath = path.resolve(__dirname, "./config.js");
if (!fs.existsSync(configPath)) {
throw new Error("Missing config file: " + configPath);
}
return require(configPath);
};
Kara.prototype._pluginPath = function _pluginPath(name) {
return [this.config.plugins.loadPath, path.sep, name, ".js"].join("");
};
// events
Kara.prototype._onRedisConnect = function _onRedisConnect() {
this.redis.select(this.config.redis.dbIndex, this._onRedisSelect.bind(this));
};
/**
* redis automatically reconnects based on options.max_attempts (defaults to
* unlimited retries)
*
* listening to redis end event and manually reconnecting will drastically
* decrease reconnection time
*/
Kara.prototype._onRedisDisconnect = function _onRedisDisconnect() {
if (this._redis) {
this._redis.end();
this._redis = null;
}
this._redisConnect();
};
Kara.prototype._onRedisError = function _onRedisError(error) {
if (error) { this.emit("redis:error", error) }
};
Kara.prototype._onRedisSelect = function _onRedisSelect(error, res) {
if (error) {
return this.emit("redis:error", error);
}
this.emit("redis:ready");
};