*/\r
var _kiwi = {};\r
\r
+_kiwi.misc = {};\r
_kiwi.model = {};\r
_kiwi.view = {};\r
_kiwi.applets = {};\r
* and data (think: plugins)\r
*/\r
_kiwi.global = {\r
+ build_version: '', // Kiwi IRC version this is built from (Set from index.html)\r
settings: undefined, // Instance of _kiwi.model.DataStore\r
- plugins: undefined,\r
- utils: undefined, // TODO: Re-usable methods\r
- user: undefined, // TODO: Limited user methods\r
- server: undefined, // TODO: Limited server methods\r
+ plugins: undefined, // Instance of _kiwi.model.PluginManager\r
+ events: undefined, // Instance of PluginInterface\r
+ rpc: undefined, // Instance of WebsocketRpc\r
+ utils: {}, // References to misc. re-usable helpers / functions\r
+\r
+ initUtils: function() {\r
+ this.utils.randomString = randomString;\r
+ this.utils.secondsToTime = secondsToTime;\r
+ this.utils.parseISO8601 = parseISO8601;\r
+ this.utils.escapeRegex = escapeRegex;\r
+ this.utils.formatIRCMsg = formatIRCMsg;\r
+ this.utils.styleText = styleText;\r
+ this.utils.hsl2rgb = hsl2rgb;\r
+ },\r
\r
- // TODO: think of a better term for this as it will also refer to queries\r
- channels: undefined, // TODO: Limited access to panels list\r
+ addMediaMessageType: function(match, buildHtml) {\r
+ _kiwi.view.MediaMessage.addType(match, buildHtml);\r
+ },\r
\r
// Event managers for plugins\r
components: {\r
EventComponent: function(event_source, proxy_event_name) {\r
+ /*\r
+ * proxyEvent() listens for events then re-triggers them on its own\r
+ * event emitter. Why? So we can .off() on this emitter without\r
+ * effecting the source of events. Handy for plugins that we don't\r
+ * trust meddling with the core events.\r
+ *\r
+ * If listening for 'all' events the arguments are as follows:\r
+ * 1. Name of the triggered event\r
+ * 2. The event data\r
+ * For all other events, we only have one argument:\r
+ * 1. The event data\r
+ *\r
+ * When this is used via `new kiwi.components.Network()`, this listens\r
+ * for 'all' events so the first argument is the event name which is\r
+ * the connection ID. We don't want to re-trigger this event name so\r
+ * we need to juggle the arguments to find the real event name we want\r
+ * to emit.\r
+ */\r
function proxyEvent(event_name, event_data) {\r
- if (proxy_event_name !== 'all') {\r
+ if (proxy_event_name == 'all') {\r
+ } else {\r
event_data = event_name.event_data;\r
- event_name = event_name.event_name\r
+ event_name = event_name.event_name;\r
}\r
-//console.log(proxy_event_name, event_name, event_data);\r
+\r
this.trigger(event_name, event_data);\r
}\r
\r
// The event we are to proxy\r
proxy_event_name = proxy_event_name || 'all';\r
\r
-\r
_.extend(this, Backbone.Events);\r
this._source = event_source;\r
\r
Network: function(connection_id) {\r
var connection_event;\r
\r
+ // If no connection id given, use all connections\r
if (typeof connection_id !== 'undefined') {\r
connection_event = 'connection:' + connection_id.toString();\r
+ } else {\r
+ connection_event = 'connection';\r
}\r
\r
+ // Helper to get the network object\r
+ var getNetwork = function() {\r
+ var network = typeof connection_id === 'undefined' ?\r
+ _kiwi.app.connections.active_connection :\r
+ _kiwi.app.connections.getByConnectionId(connection_id);\r
+\r
+ return network ?\r
+ network :\r
+ undefined;\r
+ };\r
+\r
+ // Create the return object (events proxy from the gateway)\r
var obj = new this.EventComponent(_kiwi.gateway, connection_event);\r
+\r
+ // Proxy several gateway functions onto the return object\r
var funcs = {\r
kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic',\r
part: 'part', join: 'join', action: 'action', ctcp: 'ctcp',\r
- notice: 'notice', msg: 'privmsg', changeNick: 'changeNick'\r
+ ctcpRequest: 'ctcpRequest', ctcpResponse: 'ctcpResponse',\r
+ notice: 'notice', msg: 'privmsg', say: 'privmsg',\r
+ changeNick: 'changeNick', channelInfo: 'channelInfo',\r
+ mode: 'mode', quit: 'quit'\r
};\r
\r
- // Proxy each gateway method\r
_.each(funcs, function(gateway_fn, func_name) {\r
obj[func_name] = function() {\r
var fn_name = gateway_fn;\r
};\r
});\r
\r
+ // Now for some network related functions...\r
+ obj.createQuery = function(nick) {\r
+ var network, restricted_keys;\r
+\r
+ network = getNetwork();\r
+ if (!network) {\r
+ return;\r
+ }\r
+\r
+ return network.createQuery(nick);\r
+ };\r
+\r
+ // Add the networks getters/setters\r
+ obj.get = function(name) {\r
+ var network, restricted_keys;\r
+\r
+ network = getNetwork();\r
+ if (!network) {\r
+ return;\r
+ }\r
+\r
+ restricted_keys = [\r
+ 'password'\r
+ ];\r
+ if (restricted_keys.indexOf(name) > -1) {\r
+ return undefined;\r
+ }\r
+\r
+ return network.get(name);\r
+ };\r
+\r
+ obj.set = function() {\r
+ var network = getNetwork();\r
+ if (!network) {\r
+ return;\r
+ }\r
+\r
+ return network.set.apply(network, arguments);\r
+ };\r
+\r
return obj;\r
},\r
\r
ControlInput: function() {\r
var obj = new this.EventComponent(_kiwi.app.controlbox);\r
var funcs = {\r
- processInput: 'run', addPluginIcon: 'addPluginIcon'\r
+ run: 'processInput', addPluginIcon: 'addPluginIcon'\r
};\r
\r
_.each(funcs, function(controlbox_fn, func_name) {\r
};\r
});\r
\r
+ // Give access to the control input textarea\r
+ obj.input = _kiwi.app.controlbox.$('.inp');\r
+\r
return obj;\r
}\r
},\r
\r
// Entry point to start the kiwi application\r
- start: function (opts, callback) {\r
- var continueStart, locale;\r
+ init: function (opts, callback) {\r
+ var locale_promise, theme_promise,\r
+ that = this;\r
+\r
opts = opts || {};\r
\r
- // Load the plugin manager\r
- _kiwi.global.plugins = new _kiwi.model.PluginManager();\r
+ this.initUtils();\r
\r
// Set up the settings datastore\r
_kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings');\r
_kiwi.global.settings.load();\r
\r
- continueStart = function (locale, s, xhr) {\r
- if (locale) {\r
- _kiwi.global.i18n = new Jed({locale_data: locale, domain: xhr.getResponseHeader('Content-Language')});\r
- } else {\r
- _kiwi.global.i18n = new Jed();\r
- }\r
+ // Set the window title\r
+ window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC';\r
\r
- _kiwi.app = new _kiwi.model.Application(opts);\r
+ locale_promise = new Promise(function (resolve) {\r
+ var locale = _kiwi.global.settings.get('locale') || 'magic';\r
+ $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', function (locale) {\r
+ if (locale) {\r
+ that.i18n = new Jed(locale);\r
+ } else {\r
+ that.i18n = new Jed();\r
+ }\r
+ resolve();\r
+ });\r
+ });\r
+\r
+ theme_promise = new Promise(function (resolve) {\r
+ var text_theme = opts.server_settings.client.settings.text_theme || 'default';\r
+ $.getJSON(opts.base_path + '/assets/text_themes/' + text_theme + '.json', function(text_theme) {\r
+ opts.text_theme = text_theme;\r
+ resolve();\r
+ });\r
+ });\r
\r
- if (opts.kiwi_server) {\r
- _kiwi.app.kiwi_server = opts.kiwi_server;\r
- }\r
+\r
+ Promise.all([locale_promise, theme_promise]).then(function () {\r
+ _kiwi.app = new _kiwi.model.Application(opts);\r
\r
// Start the client up\r
- _kiwi.app.start();\r
+ _kiwi.app.initializeInterfaces();\r
+\r
+ // Event emitter to let plugins interface with parts of kiwi\r
+ _kiwi.global.events = new PluginInterface();\r
\r
- callback && callback();\r
+ // Now everything has started up, load the plugin manager for third party plugins\r
+ _kiwi.global.plugins = new _kiwi.model.PluginManager();\r
+\r
+ callback();\r
+ });\r
+ },\r
+\r
+ start: function() {\r
+ _kiwi.app.showStartup();\r
+ },\r
+\r
+ // Allow plugins to change the startup applet\r
+ registerStartupApplet: function(startup_applet_name) {\r
+ _kiwi.app.startup_applet_name = startup_applet_name;\r
+ },\r
+\r
+ /**\r
+ * Open a new IRC connection\r
+ * @param {Object} connection_details {nick, host, port, ssl, password, options}\r
+ * @param {Function} callback function(err, network){}\r
+ */\r
+ newIrcConnection: function(connection_details, callback) {\r
+ _kiwi.gateway.newConnection(connection_details, callback);\r
+ },\r
+\r
+\r
+ /**\r
+ * Taking settings from the server and URL, extract the default server/channel/nick settings\r
+ */\r
+ defaultServerSettings: function () {\r
+ var parts;\r
+ var defaults = {\r
+ nick: '',\r
+ server: '',\r
+ port: 6667,\r
+ ssl: false,\r
+ channel: '',\r
+ channel_key: ''\r
};\r
+ var uricheck;\r
+\r
+\r
+ /**\r
+ * Get any settings set by the server\r
+ * These settings may be changed in the server selection dialog or via URL parameters\r
+ */\r
+ if (_kiwi.app.server_settings.client) {\r
+ if (_kiwi.app.server_settings.client.nick)\r
+ defaults.nick = _kiwi.app.server_settings.client.nick;\r
\r
- locale = _kiwi.global.settings.get('locale');\r
- if (!locale) {\r
- $.getJSON(opts.base_path + '/assets/locales/magic.json', continueStart);\r
- } else {\r
- $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', continueStart);\r
+ if (_kiwi.app.server_settings.client.server)\r
+ defaults.server = _kiwi.app.server_settings.client.server;\r
+\r
+ if (_kiwi.app.server_settings.client.port)\r
+ defaults.port = _kiwi.app.server_settings.client.port;\r
+\r
+ if (_kiwi.app.server_settings.client.ssl)\r
+ defaults.ssl = _kiwi.app.server_settings.client.ssl;\r
+\r
+ if (_kiwi.app.server_settings.client.channel)\r
+ defaults.channel = _kiwi.app.server_settings.client.channel;\r
+\r
+ if (_kiwi.app.server_settings.client.channel_key)\r
+ defaults.channel_key = _kiwi.app.server_settings.client.channel_key;\r
}\r
- }\r
+\r
+\r
+\r
+ /**\r
+ * Get any settings passed in the URL\r
+ * These settings may be changed in the server selection dialog\r
+ */\r
+\r
+ // Any query parameters first\r
+ if (getQueryVariable('nick'))\r
+ defaults.nick = getQueryVariable('nick');\r
+\r
+ if (window.location.hash)\r
+ defaults.channel = window.location.hash;\r
+\r
+\r
+ // Process the URL part by part, extracting as we go\r
+ parts = window.location.pathname.toString().replace(_kiwi.app.get('base_path'), '').split('/');\r
+\r
+ if (parts.length > 0) {\r
+ parts.shift();\r
+\r
+ if (parts.length > 0 && parts[0]) {\r
+ // Check to see if we're dealing with an irc: uri, or whether we need to extract the server/channel info from the HTTP URL path.\r
+ uricheck = parts[0].substr(0, 7).toLowerCase();\r
+ if ((uricheck === 'ircs%3a') || (uricheck.substr(0,6) === 'irc%3a')) {\r
+ parts[0] = decodeURIComponent(parts[0]);\r
+ // irc[s]://<host>[:<port>]/[<channel>[?<password>]]\r
+ uricheck = /^irc(s)?:(?:\/\/?)?([^:\/]+)(?::([0-9]+))?(?:(?:\/)([^\?]*)(?:(?:\?)(.*))?)?$/.exec(parts[0]);\r
+ /*\r
+ uricheck[1] = ssl (optional)\r
+ uricheck[2] = host\r
+ uricheck[3] = port (optional)\r
+ uricheck[4] = channel (optional)\r
+ uricheck[5] = channel key (optional, channel must also be set)\r
+ */\r
+ if (uricheck) {\r
+ if (typeof uricheck[1] !== 'undefined') {\r
+ defaults.ssl = true;\r
+ if (defaults.port === 6667) {\r
+ defaults.port = 6697;\r
+ }\r
+ }\r
+ defaults.server = uricheck[2];\r
+ if (typeof uricheck[3] !== 'undefined') {\r
+ defaults.port = uricheck[3];\r
+ }\r
+ if (typeof uricheck[4] !== 'undefined') {\r
+ defaults.channel = '#' + uricheck[4];\r
+ if (typeof uricheck[5] !== 'undefined') {\r
+ defaults.channel_key = uricheck[5];\r
+ }\r
+ }\r
+ }\r
+ parts = [];\r
+ } else {\r
+ // Extract the port+ssl if we find one\r
+ if (parts[0].search(/:/) > 0) {\r
+ defaults.port = parts[0].substring(parts[0].search(/:/) + 1);\r
+ defaults.server = parts[0].substring(0, parts[0].search(/:/));\r
+ if (defaults.port[0] === '+') {\r
+ defaults.port = parseInt(defaults.port.substring(1), 10);\r
+ defaults.ssl = true;\r
+ } else {\r
+ defaults.ssl = false;\r
+ }\r
+\r
+ } else {\r
+ defaults.server = parts[0];\r
+ }\r
+\r
+ parts.shift();\r
+ }\r
+ }\r
+\r
+ if (parts.length > 0 && parts[0]) {\r
+ defaults.channel = '#' + parts[0];\r
+ parts.shift();\r
+ }\r
+ }\r
+\r
+ // If any settings have been given by the server.. override any auto detected settings\r
+ /**\r
+ * Get any server restrictions as set in the server config\r
+ * These settings can not be changed in the server selection dialog\r
+ */\r
+ if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {\r
+ if (_kiwi.app.server_settings.connection.server) {\r
+ defaults.server = _kiwi.app.server_settings.connection.server;\r
+ }\r
+\r
+ if (_kiwi.app.server_settings.connection.port) {\r
+ defaults.port = _kiwi.app.server_settings.connection.port;\r
+ }\r
+\r
+ if (_kiwi.app.server_settings.connection.ssl) {\r
+ defaults.ssl = _kiwi.app.server_settings.connection.ssl;\r
+ }\r
+\r
+ if (_kiwi.app.server_settings.connection.channel) {\r
+ defaults.channel = _kiwi.app.server_settings.connection.channel;\r
+ }\r
+\r
+ if (_kiwi.app.server_settings.connection.channel_key) {\r
+ defaults.channel_key = _kiwi.app.server_settings.connection.channel_key;\r
+ }\r
+\r
+ if (_kiwi.app.server_settings.connection.nick) {\r
+ defaults.nick = _kiwi.app.server_settings.connection.nick;\r
+ }\r
+ }\r
+\r
+ // Set any random numbers if needed\r
+ defaults.nick = defaults.nick.replace('?', Math.floor(Math.random() * 100000).toString());\r
+\r
+ if (getQueryVariable('encoding'))\r
+ defaults.encoding = getQueryVariable('encoding');\r
+\r
+ return defaults;\r
+ },\r
};\r
\r
\r
} else {\r
// Not within a closure so set a var in the current scope\r
var kiwi = _kiwi.global;\r
-}
\ No newline at end of file
+}\r