.say() alias .msg() on public Network object
[KiwiIRC.git] / client / src / app.js
CommitLineData
eaaf73b0 1// Holds anything kiwi client specific (ie. front, gateway, _kiwi.plugs..)\r
9df70c63
D
2/**\r
3* @namespace\r
4*/\r
eaaf73b0 5var _kiwi = {};\r
9df70c63 6\r
41cba2fd 7_kiwi.misc = {};\r
eaaf73b0
D
8_kiwi.model = {};\r
9_kiwi.view = {};\r
10_kiwi.applets = {};\r
b62c8381
D
11\r
12\r
13/**\r
14 * A global container for third party access\r
15 * Will be used to access a limited subset of kiwi functionality\r
16 * and data (think: plugins)\r
17 */\r
eaaf73b0 18_kiwi.global = {\r
4c424593 19 build_version: '', // Kiwi IRC version this is built from (Set from index.html)\r
161b5673 20 settings: undefined, // Instance of _kiwi.model.DataStore\r
2a89ba11
D
21 plugins: undefined, // Instance of _kiwi.model.PluginManager\r
22 events: undefined, // Instance of PluginInterface\r
c6629f51 23 rpc: undefined, // Instance of WebsocketRpc\r
1e9f97d6
D
24 utils: {}, // References to misc. re-usable helpers / functions\r
25\r
26 initUtils: function() {\r
27 this.utils.randomString = randomString;\r
28 this.utils.secondsToTime = secondsToTime;\r
29 this.utils.parseISO8601 = parseISO8601;\r
30 this.utils.escapeRegex = escapeRegex;\r
31 this.utils.formatIRCMsg = formatIRCMsg;\r
32 this.utils.styleText = styleText;\r
33 this.utils.hsl2rgb = hsl2rgb;\r
34 },\r
35\r
f1452889
D
36 addMediaMessageType: function(match, buildHtml) {\r
37 _kiwi.view.MediaMessage.addType(match, buildHtml);\r
38 },\r
39\r
161b5673
D
40 // Event managers for plugins\r
41 components: {\r
42 EventComponent: function(event_source, proxy_event_name) {\r
9b609554
D
43 /*\r
44 * proxyEvent() listens for events then re-triggers them on its own\r
45 * event emitter. Why? So we can .off() on this emitter without\r
46 * effecting the source of events. Handy for plugins that we don't\r
47 * trust meddling with the core events.\r
48 *\r
49 * If listening for 'all' events the arguments are as follows:\r
50 * 1. Name of the triggered event\r
51 * 2. The event data\r
52 * For all other events, we only have one argument:\r
53 * 1. The event data\r
54 *\r
55 * When this is used via `new kiwi.components.Network()`, this listens\r
56 * for 'all' events so the first argument is the event name which is\r
57 * the connection ID. We don't want to re-trigger this event name so\r
58 * we need to juggle the arguments to find the real event name we want\r
59 * to emit.\r
60 */\r
161b5673 61 function proxyEvent(event_name, event_data) {\r
9b609554 62 if (proxy_event_name == 'all') {\r
9b609554 63 } else {\r
161b5673 64 event_data = event_name.event_data;\r
f1452889 65 event_name = event_name.event_name;\r
161b5673 66 }\r
f1452889 67\r
161b5673
D
68 this.trigger(event_name, event_data);\r
69 }\r
70\r
71 // The event we are to proxy\r
72 proxy_event_name = proxy_event_name || 'all';\r
73\r
161b5673
D
74 _.extend(this, Backbone.Events);\r
75 this._source = event_source;\r
76\r
77 // Proxy the events to this dispatcher\r
78 event_source.on(proxy_event_name, proxyEvent, this);\r
79\r
80 // Clean up this object\r
81 this.dispose = function () {\r
82 event_source.off(proxy_event_name, proxyEvent);\r
83 this.off();\r
84 delete this.event_source;\r
85 };\r
86 },\r
87\r
88 Network: function(connection_id) {\r
89 var connection_event;\r
90\r
a9b1c5d6 91 // If no connection id given, use all connections\r
161b5673
D
92 if (typeof connection_id !== 'undefined') {\r
93 connection_event = 'connection:' + connection_id.toString();\r
18ae1a72
D
94 } else {\r
95 connection_event = 'connection';\r
161b5673
D
96 }\r
97\r
a9b1c5d6
D
98 // Helper to get the network object\r
99 var getNetwork = function() {\r
100 var network = typeof connection_id === 'undefined' ?\r
101 _kiwi.app.connections.active_connection :\r
102 _kiwi.app.connections.getByConnectionId(connection_id);\r
103\r
104 return network ?\r
105 network :\r
106 undefined;\r
107 };\r
108\r
109 // Create the return object (events proxy from the gateway)\r
161b5673 110 var obj = new this.EventComponent(_kiwi.gateway, connection_event);\r
a9b1c5d6
D
111\r
112 // Proxy several gateway functions onto the return object\r
161b5673
D
113 var funcs = {\r
114 kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic',\r
115 part: 'part', join: 'join', action: 'action', ctcp: 'ctcp',\r
9de52d29 116 ctcpRequest: 'ctcpRequest', ctcpResponse: 'ctcpResponse',\r
299a4c35
D
117 notice: 'notice', msg: 'privmsg', say: 'privmsg',\r
118 changeNick: 'changeNick', channelInfo: 'channelInfo',\r
119 mode: 'mode', quit: 'quit'\r
161b5673
D
120 };\r
121\r
161b5673
D
122 _.each(funcs, function(gateway_fn, func_name) {\r
123 obj[func_name] = function() {\r
124 var fn_name = gateway_fn;\r
125\r
126 // Add connection_id to the argument list\r
127 var args = Array.prototype.slice.call(arguments, 0);\r
128 args.unshift(connection_id);\r
129\r
130 // Call the gateway function on behalf of this connection\r
131 return _kiwi.gateway[fn_name].apply(_kiwi.gateway, args);\r
132 };\r
133 });\r
134\r
6af0c7e0
D
135 // Now for some network related functions...\r
136 obj.createQuery = function(nick) {\r
137 var network, restricted_keys;\r
138\r
139 network = getNetwork();\r
140 if (!network) {\r
141 return;\r
142 }\r
143\r
144 return network.createQuery(nick);\r
145 };\r
146\r
a9b1c5d6 147 // Add the networks getters/setters\r
15221ec7
D
148 obj.get = function(name) {\r
149 var network, restricted_keys;\r
150\r
151 network = getNetwork();\r
a9b1c5d6
D
152 if (!network) {\r
153 return;\r
154 }\r
155\r
15221ec7
D
156 restricted_keys = [\r
157 'password'\r
158 ];\r
159 if (restricted_keys.indexOf(name) > -1) {\r
160 return undefined;\r
161 }\r
162\r
163 return network.get(name);\r
a9b1c5d6
D
164 };\r
165\r
166 obj.set = function() {\r
167 var network = getNetwork();\r
168 if (!network) {\r
169 return;\r
170 }\r
171\r
172 return network.set.apply(network, arguments);\r
173 };\r
174\r
161b5673
D
175 return obj;\r
176 },\r
177\r
178 ControlInput: function() {\r
179 var obj = new this.EventComponent(_kiwi.app.controlbox);\r
180 var funcs = {\r
d63a5832 181 run: 'processInput', addPluginIcon: 'addPluginIcon'\r
161b5673
D
182 };\r
183\r
184 _.each(funcs, function(controlbox_fn, func_name) {\r
185 obj[func_name] = function() {\r
186 var fn_name = controlbox_fn;\r
187 return _kiwi.app.controlbox[fn_name].apply(_kiwi.app.controlbox, arguments);\r
188 };\r
189 });\r
190\r
191 return obj;\r
192 }\r
193 },\r
194\r
195 // Entry point to start the kiwi application\r
6b8fbed0 196 init: function (opts, callback) {\r
de761906 197 var locale_promise, theme_promise,\r
ae007e1e 198 that = this;\r
de761906 199\r
161b5673 200 opts = opts || {};\r
b62c8381 201\r
1e9f97d6
D
202 this.initUtils();\r
203\r
ae007e1e
JA
204 // Set up the settings datastore\r
205 _kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings');\r
206 _kiwi.global.settings.load();\r
207\r
208 // Set the window title\r
209 window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC';\r
210\r
de761906 211 locale_promise = new Promise(function (resolve) {\r
ae007e1e
JA
212 var locale = _kiwi.global.settings.get('locale') || 'magic';\r
213 $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', function (locale) {\r
214 if (locale) {\r
215 that.i18n = new Jed(locale);\r
216 } else {\r
217 that.i18n = new Jed();\r
218 }\r
219 resolve();\r
220 });\r
221 });\r
222\r
de761906 223 theme_promise = new Promise(function (resolve) {\r
ae007e1e
JA
224 var text_theme = opts.server_settings.client.settings.text_theme || 'default';\r
225 $.getJSON(opts.base_path + '/assets/text_themes/' + text_theme + '.json', function(text_theme) {\r
226 opts.text_theme = text_theme;\r
227 resolve();\r
228 });\r
229 });\r
230\r
231\r
de761906 232 Promise.all([locale_promise, theme_promise]).then(function () {\r
161b5673 233 _kiwi.app = new _kiwi.model.Application(opts);\r
0fa2ca42 234\r
161b5673 235 // Start the client up\r
6b8fbed0 236 _kiwi.app.initializeInterfaces();\r
62c18d2d 237\r
2a89ba11
D
238 // Event emitter to let plugins interface with parts of kiwi\r
239 _kiwi.global.events = new PluginInterface();\r
240\r
f66c4823
D
241 // Now everything has started up, load the plugin manager for third party plugins\r
242 _kiwi.global.plugins = new _kiwi.model.PluginManager();\r
243\r
c3d988bc
D
244 callback();\r
245 });\r
6b8fbed0
D
246 },\r
247\r
248 start: function() {\r
77c84a91 249 _kiwi.app.showStartup();\r
6b8fbed0
D
250 },\r
251\r
252 // Allow plugins to change the startup applet\r
253 registerStartupApplet: function(startup_applet_name) {\r
254 _kiwi.app.startup_applet_name = startup_applet_name;\r
e537d683
D
255 },\r
256\r
257 /**\r
258 * Open a new IRC connection\r
259 * @param {Object} connection_details {nick, host, port, ssl, password, options}\r
260 * @param {Function} callback function(err, network){}\r
261 */\r
262 newIrcConnection: function(connection_details, callback) {\r
263 _kiwi.gateway.newConnection(connection_details, callback);\r
d0734219
D
264 },\r
265\r
266\r
267 /**\r
268 * Taking settings from the server and URL, extract the default server/channel/nick settings\r
269 */\r
270 defaultServerSettings: function () {\r
271 var parts;\r
272 var defaults = {\r
273 nick: '',\r
274 server: '',\r
275 port: 6667,\r
276 ssl: false,\r
277 channel: '',\r
278 channel_key: ''\r
279 };\r
280 var uricheck;\r
281\r
282\r
283 /**\r
284 * Get any settings set by the server\r
285 * These settings may be changed in the server selection dialog or via URL parameters\r
286 */\r
287 if (_kiwi.app.server_settings.client) {\r
288 if (_kiwi.app.server_settings.client.nick)\r
289 defaults.nick = _kiwi.app.server_settings.client.nick;\r
290\r
291 if (_kiwi.app.server_settings.client.server)\r
292 defaults.server = _kiwi.app.server_settings.client.server;\r
293\r
294 if (_kiwi.app.server_settings.client.port)\r
295 defaults.port = _kiwi.app.server_settings.client.port;\r
296\r
297 if (_kiwi.app.server_settings.client.ssl)\r
298 defaults.ssl = _kiwi.app.server_settings.client.ssl;\r
299\r
300 if (_kiwi.app.server_settings.client.channel)\r
301 defaults.channel = _kiwi.app.server_settings.client.channel;\r
302\r
303 if (_kiwi.app.server_settings.client.channel_key)\r
304 defaults.channel_key = _kiwi.app.server_settings.client.channel_key;\r
305 }\r
306\r
307\r
308\r
309 /**\r
310 * Get any settings passed in the URL\r
311 * These settings may be changed in the server selection dialog\r
312 */\r
313\r
314 // Any query parameters first\r
315 if (getQueryVariable('nick'))\r
316 defaults.nick = getQueryVariable('nick');\r
317\r
318 if (window.location.hash)\r
319 defaults.channel = window.location.hash;\r
320\r
321\r
322 // Process the URL part by part, extracting as we go\r
323 parts = window.location.pathname.toString().replace(_kiwi.app.get('base_path'), '').split('/');\r
324\r
325 if (parts.length > 0) {\r
326 parts.shift();\r
327\r
328 if (parts.length > 0 && parts[0]) {\r
329 // 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
330 uricheck = parts[0].substr(0, 7).toLowerCase();\r
331 if ((uricheck === 'ircs%3a') || (uricheck.substr(0,6) === 'irc%3a')) {\r
332 parts[0] = decodeURIComponent(parts[0]);\r
333 // irc[s]://<host>[:<port>]/[<channel>[?<password>]]\r
334 uricheck = /^irc(s)?:(?:\/\/?)?([^:\/]+)(?::([0-9]+))?(?:(?:\/)([^\?]*)(?:(?:\?)(.*))?)?$/.exec(parts[0]);\r
335 /*\r
336 uricheck[1] = ssl (optional)\r
337 uricheck[2] = host\r
338 uricheck[3] = port (optional)\r
339 uricheck[4] = channel (optional)\r
340 uricheck[5] = channel key (optional, channel must also be set)\r
341 */\r
342 if (uricheck) {\r
343 if (typeof uricheck[1] !== 'undefined') {\r
344 defaults.ssl = true;\r
345 if (defaults.port === 6667) {\r
346 defaults.port = 6697;\r
347 }\r
348 }\r
349 defaults.server = uricheck[2];\r
350 if (typeof uricheck[3] !== 'undefined') {\r
351 defaults.port = uricheck[3];\r
352 }\r
353 if (typeof uricheck[4] !== 'undefined') {\r
354 defaults.channel = '#' + uricheck[4];\r
355 if (typeof uricheck[5] !== 'undefined') {\r
356 defaults.channel_key = uricheck[5];\r
357 }\r
358 }\r
359 }\r
360 parts = [];\r
361 } else {\r
362 // Extract the port+ssl if we find one\r
363 if (parts[0].search(/:/) > 0) {\r
364 defaults.port = parts[0].substring(parts[0].search(/:/) + 1);\r
365 defaults.server = parts[0].substring(0, parts[0].search(/:/));\r
366 if (defaults.port[0] === '+') {\r
367 defaults.port = parseInt(defaults.port.substring(1), 10);\r
368 defaults.ssl = true;\r
369 } else {\r
370 defaults.ssl = false;\r
371 }\r
372\r
373 } else {\r
374 defaults.server = parts[0];\r
375 }\r
376\r
377 parts.shift();\r
378 }\r
379 }\r
380\r
381 if (parts.length > 0 && parts[0]) {\r
382 defaults.channel = '#' + parts[0];\r
383 parts.shift();\r
384 }\r
385 }\r
386\r
387 // If any settings have been given by the server.. override any auto detected settings\r
388 /**\r
389 * Get any server restrictions as set in the server config\r
390 * These settings can not be changed in the server selection dialog\r
391 */\r
392 if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {\r
393 if (_kiwi.app.server_settings.connection.server) {\r
394 defaults.server = _kiwi.app.server_settings.connection.server;\r
395 }\r
396\r
397 if (_kiwi.app.server_settings.connection.port) {\r
398 defaults.port = _kiwi.app.server_settings.connection.port;\r
399 }\r
400\r
401 if (_kiwi.app.server_settings.connection.ssl) {\r
402 defaults.ssl = _kiwi.app.server_settings.connection.ssl;\r
403 }\r
404\r
405 if (_kiwi.app.server_settings.connection.channel) {\r
406 defaults.channel = _kiwi.app.server_settings.connection.channel;\r
407 }\r
408\r
409 if (_kiwi.app.server_settings.connection.channel_key) {\r
410 defaults.channel_key = _kiwi.app.server_settings.connection.channel_key;\r
411 }\r
412\r
413 if (_kiwi.app.server_settings.connection.nick) {\r
414 defaults.nick = _kiwi.app.server_settings.connection.nick;\r
415 }\r
416 }\r
417\r
418 // Set any random numbers if needed\r
419 defaults.nick = defaults.nick.replace('?', Math.floor(Math.random() * 100000).toString());\r
420\r
421 if (getQueryVariable('encoding'))\r
422 defaults.encoding = getQueryVariable('encoding');\r
423\r
424 return defaults;\r
425 },\r
b62c8381
D
426};\r
427\r
428\r
429\r
430// If within a closure, expose the kiwi globals\r
431if (typeof global !== 'undefined') {\r
161b5673 432 global.kiwi = _kiwi.global;\r
eaaf73b0 433} else {\r
161b5673
D
434 // Not within a closure so set a var in the current scope\r
435 var kiwi = _kiwi.global;\r
6636cc9e 436}\r