Client plugin RPC call improvement
[KiwiIRC.git] / client / src / app.js
1 // Holds anything kiwi client specific (ie. front, gateway, _kiwi.plugs..)
2 /**
3 * @namespace
4 */
5 var _kiwi = {};
6
7 _kiwi.model = {};
8 _kiwi.view = {};
9 _kiwi.applets = {};
10
11
12 /**
13 * A global container for third party access
14 * Will be used to access a limited subset of kiwi functionality
15 * and data (think: plugins)
16 */
17 _kiwi.global = {
18 build_version: '', // Kiwi IRC version this is built from (Set from index.html)
19 settings: undefined, // Instance of _kiwi.model.DataStore
20 plugins: undefined, // Instance of _kiwi.model.PluginManager
21 events: undefined, // Instance of PluginInterface
22 utils: {}, // TODO: Re-usable methods
23 rpc: function() {
24 _kiwi.gateway.rpc.call.call(_kiwi.gateway.rpc, arguments);
25 },
26
27 addMediaMessageType: function(match, buildHtml) {
28 _kiwi.view.MediaMessage.addType(match, buildHtml);
29 },
30
31 // Event managers for plugins
32 components: {
33 EventComponent: function(event_source, proxy_event_name) {
34 function proxyEvent(event_name, event_data) {
35 if (proxy_event_name !== 'all') {
36 event_data = event_name.event_data;
37 event_name = event_name.event_name;
38 }
39
40 this.trigger(event_name, event_data);
41 }
42
43 // The event we are to proxy
44 proxy_event_name = proxy_event_name || 'all';
45
46
47 _.extend(this, Backbone.Events);
48 this._source = event_source;
49
50 // Proxy the events to this dispatcher
51 event_source.on(proxy_event_name, proxyEvent, this);
52
53 // Clean up this object
54 this.dispose = function () {
55 event_source.off(proxy_event_name, proxyEvent);
56 this.off();
57 delete this.event_source;
58 };
59 },
60
61 Network: function(connection_id) {
62 var connection_event;
63
64 if (typeof connection_id !== 'undefined') {
65 connection_event = 'connection:' + connection_id.toString();
66 }
67
68 var obj = new this.EventComponent(_kiwi.gateway, connection_event);
69 var funcs = {
70 kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic',
71 part: 'part', join: 'join', action: 'action', ctcp: 'ctcp',
72 ctcpRequest: 'ctcpRequest', ctcpResponse: 'ctcpResponse',
73 notice: 'notice', msg: 'privmsg', changeNick: 'changeNick',
74 channelInfo: 'channelInfo', mode: 'mode'
75 };
76
77 // Proxy each gateway method
78 _.each(funcs, function(gateway_fn, func_name) {
79 obj[func_name] = function() {
80 var fn_name = gateway_fn;
81
82 // Add connection_id to the argument list
83 var args = Array.prototype.slice.call(arguments, 0);
84 args.unshift(connection_id);
85
86 // Call the gateway function on behalf of this connection
87 return _kiwi.gateway[fn_name].apply(_kiwi.gateway, args);
88 };
89 });
90
91 return obj;
92 },
93
94 ControlInput: function() {
95 var obj = new this.EventComponent(_kiwi.app.controlbox);
96 var funcs = {
97 run: 'processInput', addPluginIcon: 'addPluginIcon'
98 };
99
100 _.each(funcs, function(controlbox_fn, func_name) {
101 obj[func_name] = function() {
102 var fn_name = controlbox_fn;
103 return _kiwi.app.controlbox[fn_name].apply(_kiwi.app.controlbox, arguments);
104 };
105 });
106
107 return obj;
108 }
109 },
110
111 // Entry point to start the kiwi application
112 init: function (opts, callback) {
113 var jobs, locale, localeLoaded, textThemeLoaded, text_theme;
114 opts = opts || {};
115
116 jobs = new JobManager();
117 jobs.onFinish(function(locale, s, xhr) {
118 _kiwi.app = new _kiwi.model.Application(opts);
119
120 // Start the client up
121 _kiwi.app.initializeInterfaces();
122
123 // Event emitter to let plugins interface with parts of kiwi
124 _kiwi.global.events = new PluginInterface();
125
126 // Now everything has started up, load the plugin manager for third party plugins
127 _kiwi.global.plugins = new _kiwi.model.PluginManager();
128
129 callback();
130 });
131
132 textThemeLoaded = function(text_theme, s, xhr) {
133 opts.text_theme = text_theme;
134
135 jobs.finishJob('load_text_theme');
136 };
137
138 localeLoaded = function(locale, s, xhr) {
139 if (locale) {
140 _kiwi.global.i18n = new Jed(locale);
141 } else {
142 _kiwi.global.i18n = new Jed();
143 }
144
145 jobs.finishJob('load_locale');
146 };
147
148 // Set up the settings datastore
149 _kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings');
150 _kiwi.global.settings.load();
151
152 // Set the window title
153 window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC';
154
155 jobs.registerJob('load_locale');
156 locale = _kiwi.global.settings.get('locale');
157 if (!locale) {
158 $.getJSON(opts.base_path + '/assets/locales/magic.json', localeLoaded);
159 } else {
160 $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', localeLoaded);
161 }
162
163 jobs.registerJob('load_text_theme');
164 text_theme = opts.server_settings.client.settings.text_theme || 'default';
165 $.getJSON(opts.base_path + '/assets/text_themes/' + text_theme + '.json', textThemeLoaded);
166 },
167
168 start: function() {
169 _kiwi.app.showStartup();
170 },
171
172 // Allow plugins to change the startup applet
173 registerStartupApplet: function(startup_applet_name) {
174 _kiwi.app.startup_applet_name = startup_applet_name;
175 },
176
177 /**
178 * Open a new IRC connection
179 * @param {Object} connection_details {nick, host, port, ssl, password, options}
180 * @param {Function} callback function(err, network){}
181 */
182 newIrcConnection: function(connection_details, callback) {
183 _kiwi.gateway.newConnection(connection_details, callback);
184 },
185
186
187 /**
188 * Taking settings from the server and URL, extract the default server/channel/nick settings
189 */
190 defaultServerSettings: function () {
191 var parts;
192 var defaults = {
193 nick: '',
194 server: '',
195 port: 6667,
196 ssl: false,
197 channel: '',
198 channel_key: ''
199 };
200 var uricheck;
201
202
203 /**
204 * Get any settings set by the server
205 * These settings may be changed in the server selection dialog or via URL parameters
206 */
207 if (_kiwi.app.server_settings.client) {
208 if (_kiwi.app.server_settings.client.nick)
209 defaults.nick = _kiwi.app.server_settings.client.nick;
210
211 if (_kiwi.app.server_settings.client.server)
212 defaults.server = _kiwi.app.server_settings.client.server;
213
214 if (_kiwi.app.server_settings.client.port)
215 defaults.port = _kiwi.app.server_settings.client.port;
216
217 if (_kiwi.app.server_settings.client.ssl)
218 defaults.ssl = _kiwi.app.server_settings.client.ssl;
219
220 if (_kiwi.app.server_settings.client.channel)
221 defaults.channel = _kiwi.app.server_settings.client.channel;
222
223 if (_kiwi.app.server_settings.client.channel_key)
224 defaults.channel_key = _kiwi.app.server_settings.client.channel_key;
225 }
226
227
228
229 /**
230 * Get any settings passed in the URL
231 * These settings may be changed in the server selection dialog
232 */
233
234 // Any query parameters first
235 if (getQueryVariable('nick'))
236 defaults.nick = getQueryVariable('nick');
237
238 if (window.location.hash)
239 defaults.channel = window.location.hash;
240
241
242 // Process the URL part by part, extracting as we go
243 parts = window.location.pathname.toString().replace(_kiwi.app.get('base_path'), '').split('/');
244
245 if (parts.length > 0) {
246 parts.shift();
247
248 if (parts.length > 0 && parts[0]) {
249 // 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.
250 uricheck = parts[0].substr(0, 7).toLowerCase();
251 if ((uricheck === 'ircs%3a') || (uricheck.substr(0,6) === 'irc%3a')) {
252 parts[0] = decodeURIComponent(parts[0]);
253 // irc[s]://<host>[:<port>]/[<channel>[?<password>]]
254 uricheck = /^irc(s)?:(?:\/\/?)?([^:\/]+)(?::([0-9]+))?(?:(?:\/)([^\?]*)(?:(?:\?)(.*))?)?$/.exec(parts[0]);
255 /*
256 uricheck[1] = ssl (optional)
257 uricheck[2] = host
258 uricheck[3] = port (optional)
259 uricheck[4] = channel (optional)
260 uricheck[5] = channel key (optional, channel must also be set)
261 */
262 if (uricheck) {
263 if (typeof uricheck[1] !== 'undefined') {
264 defaults.ssl = true;
265 if (defaults.port === 6667) {
266 defaults.port = 6697;
267 }
268 }
269 defaults.server = uricheck[2];
270 if (typeof uricheck[3] !== 'undefined') {
271 defaults.port = uricheck[3];
272 }
273 if (typeof uricheck[4] !== 'undefined') {
274 defaults.channel = '#' + uricheck[4];
275 if (typeof uricheck[5] !== 'undefined') {
276 defaults.channel_key = uricheck[5];
277 }
278 }
279 }
280 parts = [];
281 } else {
282 // Extract the port+ssl if we find one
283 if (parts[0].search(/:/) > 0) {
284 defaults.port = parts[0].substring(parts[0].search(/:/) + 1);
285 defaults.server = parts[0].substring(0, parts[0].search(/:/));
286 if (defaults.port[0] === '+') {
287 defaults.port = parseInt(defaults.port.substring(1), 10);
288 defaults.ssl = true;
289 } else {
290 defaults.ssl = false;
291 }
292
293 } else {
294 defaults.server = parts[0];
295 }
296
297 parts.shift();
298 }
299 }
300
301 if (parts.length > 0 && parts[0]) {
302 defaults.channel = '#' + parts[0];
303 parts.shift();
304 }
305 }
306
307 // If any settings have been given by the server.. override any auto detected settings
308 /**
309 * Get any server restrictions as set in the server config
310 * These settings can not be changed in the server selection dialog
311 */
312 if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {
313 if (_kiwi.app.server_settings.connection.server) {
314 defaults.server = _kiwi.app.server_settings.connection.server;
315 }
316
317 if (_kiwi.app.server_settings.connection.port) {
318 defaults.port = _kiwi.app.server_settings.connection.port;
319 }
320
321 if (_kiwi.app.server_settings.connection.ssl) {
322 defaults.ssl = _kiwi.app.server_settings.connection.ssl;
323 }
324
325 if (_kiwi.app.server_settings.connection.channel) {
326 defaults.channel = _kiwi.app.server_settings.connection.channel;
327 }
328
329 if (_kiwi.app.server_settings.connection.channel_key) {
330 defaults.channel_key = _kiwi.app.server_settings.connection.channel_key;
331 }
332
333 if (_kiwi.app.server_settings.connection.nick) {
334 defaults.nick = _kiwi.app.server_settings.connection.nick;
335 }
336 }
337
338 // Set any random numbers if needed
339 defaults.nick = defaults.nick.replace('?', Math.floor(Math.random() * 100000).toString());
340
341 if (getQueryVariable('encoding'))
342 defaults.encoding = getQueryVariable('encoding');
343
344 return defaults;
345 },
346 };
347
348
349
350 // If within a closure, expose the kiwi globals
351 if (typeof global !== 'undefined') {
352 global.kiwi = _kiwi.global;
353 } else {
354 // Not within a closure so set a var in the current scope
355 var kiwi = _kiwi.global;
356 }