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