Merge branch 'winston' of https://github.com/M2Ys4U/KiwiIRC into winston
[KiwiIRC.git] / client / src / models / gateway.js
CommitLineData
eaaf73b0 1_kiwi.model.Gateway = function () {\r
696a66f8
D
2\r
3 // Set to a reference to this object within initialize()\r
4 var that = null;\r
5\r
696a66f8
D
6 this.initialize = function () {\r
7 that = this;\r
09c26937 8\r
696a66f8
D
9 // For ease of access. The socket.io object\r
10 this.socket = this.get('socket');\r
6228b635
D
11\r
12 this.applyEventHandlers();\r
09c26937
D
13\r
14 // Used to check if a disconnection was unplanned\r
15 this.disconnect_requested = false;\r
6228b635
D
16 };\r
17\r
18\r
19 this.applyEventHandlers = function () {\r
20 /*\r
a1629e09
D
21 kiwi.gateway.on('message:#channel', my_function);\r
22 kiwi.gateway.on('message:somenick', my_function);\r
6228b635
D
23\r
24 kiwi.gateway.on('notice:#channel', my_function);\r
25 kiwi.gateway.on('action:somenick', my_function);\r
26\r
27 kiwi.gateway.on('join:#channel', my_function);\r
28 kiwi.gateway.on('part:#channel', my_function);\r
29 kiwi.gateway.on('quit', my_function);\r
30 */\r
31 var that = this;\r
09c26937 32\r
6228b635
D
33 // Some easier handler events\r
34 this.on('onmsg', function (event) {\r
35 var source,\r
fc9b83de 36 connection = _kiwi.app.connections.getByConnectionId(event.server),\r
aef6e2a7 37 is_pm = (event.channel.toLowerCase() == connection.get('nick').toLowerCase());\r
6228b635
D
38\r
39 source = is_pm ? event.nick : event.channel;\r
09c26937 40\r
8913f3ea
D
41 that.trigger('message:' + source, event);\r
42 that.trigger('message', event);\r
6228b635
D
43\r
44 if (is_pm) {\r
6228b635 45 that.trigger('pm:' + source, event);\r
8913f3ea 46 that.trigger('pm', event);\r
6228b635
D
47 }\r
48 }, this);\r
49\r
50\r
51 this.on('onnotice', function (event) {\r
52 // The notice towards a channel or a query window?\r
53 var source = event.target || event.nick;\r
54\r
6228b635 55 this.trigger('notice:' + source, event);\r
8913f3ea 56 this.trigger('notice', event);\r
6228b635
D
57 }, this);\r
58\r
59\r
60 this.on('onaction', function (event) {\r
61 var source,\r
fc9b83de 62 connection = _kiwi.app.connections.getByConnectionId(event.server),\r
aef6e2a7 63 is_pm = (event.channel.toLowerCase() == connection.get('nick').toLowerCase());\r
6228b635
D
64\r
65 source = is_pm ? event.nick : event.channel;\r
09c26937 66\r
6228b635
D
67 that.trigger('action:' + source, event);\r
68\r
69 if (is_pm) {\r
6228b635 70 that.trigger('action:' + source, event);\r
8913f3ea 71 that.trigger('action', event);\r
6228b635
D
72 }\r
73 }, this);\r
74\r
75\r
76 this.on('ontopic', function (event) {\r
6228b635 77 that.trigger('topic:' + event.channel, event);\r
8913f3ea 78 that.trigger('topic', event);\r
6228b635 79 });\r
22373da6
D
80\r
81\r
82 this.on('onjoin', function (event) {\r
83 that.trigger('join:' + event.channel, event);\r
84 that.trigger('join', event);\r
85 });\r
86\r
696a66f8
D
87 };\r
88\r
89\r
6228b635 90\r
09c26937 91 this.reconnect = function (callback) {\r
d6eec6ed
D
92 var that = this,\r
93 transport_path;\r
94\r
09c26937 95 this.disconnect_requested = true;\r
d99e7823
D
96 this.socket.close();\r
97\r
33432128 98 this.socket = null;\r
c6a65334 99 this.connect(callback);\r
09c26937
D
100 };\r
101\r
102\r
103\r
696a66f8
D
104 /**\r
105 * Connects to the server\r
696a66f8
D
106 * @param {Function} callback A callback function to be invoked once Kiwi's server has connected to the IRC server\r
107 */\r
f2bb5380 108 this.connect = function (callback) {\r
8cc59dbe
D
109 this.connect_callback = callback;\r
110\r
e5baa247
D
111 // Keep note of the server we are connecting to\r
112 this.set('kiwi_server', _kiwi.app.kiwi_server);\r
113\r
33432128 114 this.socket = new EngineioTools.ReconnectingSocket(this.get('kiwi_server'), {\r
d99e7823 115 path: _kiwi.app.get('base_path') + '/transport',\r
d99e7823
D
116 reconnect_max_attempts: 5,\r
117 reconnect_delay: 2000\r
118 });\r
8b0eb787 119\r
33432128 120 this.rpc = new EngineioTools.Rpc(this.socket);\r
f2bb5380 121\r
696a66f8 122 this.socket.on('connect_failed', function (reason) {\r
696a66f8
D
123 this.socket.disconnect();\r
124 this.trigger("connect_fail", {reason: reason});\r
125 });\r
126\r
127 this.socket.on('error', function (e) {\r
eaaf73b0 128 console.log("_kiwi.gateway.socket.on('error')", {reason: e});\r
696a66f8
D
129 that.trigger("connect_fail", {reason: e});\r
130 });\r
131\r
132 this.socket.on('connecting', function (transport_type) {\r
eaaf73b0 133 console.log("_kiwi.gateway.socket.on('connecting')");\r
696a66f8
D
134 that.trigger("connecting");\r
135 });\r
136\r
137 /**\r
138 * Once connected to the kiwi server send the IRC connect command along\r
139 * with the IRC server details.\r
140 * A `connect` event is sent from the kiwi server once connected to the\r
141 * IRCD and the nick has been accepted.\r
142 */\r
d99e7823 143 this.socket.on('open', function () {\r
09c26937
D
144 // Reset the disconnect_requested flag\r
145 that.disconnect_requested = false;\r
146\r
28635406 147 console.log("_kiwi.gateway.socket.on('open')");\r
696a66f8
D
148 });\r
149\r
d99e7823 150 this.rpc.on('too_many_connections', function () {\r
696a66f8
D
151 that.trigger("connect_fail", {reason: 'too_many_connections'});\r
152 });\r
153\r
d99e7823 154 this.rpc.on('irc', function (response, data) {\r
696a66f8
D
155 that.parse(data.command, data.data);\r
156 });\r
157\r
d99e7823 158 this.rpc.on('kiwi', function (response, data) {\r
d2d91c10
D
159 that.parseKiwi(data.command, data.data);\r
160 });\r
161\r
696a66f8 162 this.socket.on('close', function () {\r
d99e7823 163 that.trigger("disconnect", {});\r
eaaf73b0 164 console.log("_kiwi.gateway.socket.on('close')");\r
696a66f8
D
165 });\r
166\r
d99e7823 167 this.socket.on('reconnecting', function (status) {\r
eaaf73b0 168 console.log("_kiwi.gateway.socket.on('reconnecting')");\r
d99e7823 169 that.trigger("reconnecting", {delay: status.delay, attempts: status.attempts});\r
696a66f8
D
170 });\r
171\r
d99e7823 172 this.socket.on('reconnecting_failed', function () {\r
eaaf73b0 173 console.log("_kiwi.gateway.socket.on('reconnect_failed')");\r
696a66f8
D
174 });\r
175 };\r
176\r
177\r
d6eec6ed
D
178 /**\r
179 * Return a new network object with the new connection details\r
180 */\r
2a27c998 181 this.newConnection = function(connection_info, callback_fn) {\r
d6eec6ed 182 var that = this;\r
2a27c998 183\r
d6eec6ed 184 this.makeIrcConnection(connection_info, function(err, server_num) {\r
c966123a
D
185 var connection;\r
186\r
2a27c998 187 if (!err) {\r
f2bb5380 188 if (!_kiwi.app.connections.getByConnectionId(server_num)){\r
d6eec6ed
D
189 var inf = {\r
190 connection_id: server_num,\r
191 nick: connection_info.nick,\r
192 address: connection_info.host,\r
193 port: connection_info.port,\r
194 ssl: connection_info.ssl,\r
195 password: connection_info.password\r
196 };\r
197 connection = new _kiwi.model.Network(inf);\r
c966123a 198 _kiwi.app.connections.add(connection);\r
2a27c998
D
199 }\r
200\r
d6eec6ed 201 console.log("_kiwi.gateway.socket.on('connect')", connection);\r
c966123a 202 callback_fn && callback_fn(err, connection);\r
09c26937 203\r
2a27c998
D
204 } else {\r
205 console.log("_kiwi.gateway.socket.on('error')", {reason: err});\r
206 callback_fn && callback_fn(err);\r
207 }\r
208 });\r
209 };\r
210\r
d6eec6ed
D
211\r
212 /**\r
213 * Make a new IRC connection and return its connection ID\r
214 */\r
215 this.makeIrcConnection = function(connection_info, callback_fn) {\r
216 var server_info = {\r
217 command: 'connect',\r
218 nick: connection_info.nick,\r
219 hostname: connection_info.host,\r
220 port: connection_info.port,\r
221 ssl: connection_info.ssl,\r
222 password: connection_info.password\r
223 };\r
224\r
c6a65334
D
225 connection_info.options = connection_info.options || {};\r
226\r
cc54c0a1
D
227 // A few optional parameters\r
228 if (connection_info.options.encoding)\r
229 server_info.encoding = connection_info.options.encoding;\r
230\r
d99e7823 231 this.rpc.call('kiwi', server_info, function (err, server_num) {\r
d6eec6ed
D
232 if (!err) {\r
233 callback_fn && callback_fn(err, server_num);\r
234\r
235 } else {\r
236 callback_fn && callback_fn(err);\r
237 }\r
238 });\r
239 };\r
240\r
241\r
696a66f8 242 this.isConnected = function () {\r
d99e7823
D
243 // TODO: Check this. Might want to use .readyState\r
244 return this.socket;\r
696a66f8
D
245 };\r
246\r
247\r
d2d91c10
D
248\r
249 this.parseKiwi = function (command, data) {\r
a1629e09
D
250 this.trigger('kiwi:' + command, data);\r
251 this.trigger('kiwi', data);\r
8cc59dbe
D
252\r
253 switch (command) {\r
254 case 'connected':\r
255 this.connect_callback && this.connect_callback();\r
256 delete this.connect_callback;\r
257 break;\r
258 }\r
d2d91c10 259 };\r
696a66f8
D
260 /*\r
261 Events:\r
262 msg\r
263 action\r
264 server_connect\r
265 options\r
266 motd\r
267 notice\r
268 userlist\r
269 nick\r
270 join\r
271 topic\r
272 part\r
273 kick\r
274 quit\r
275 whois\r
276 syncchannel_redirect\r
277 debug\r
278 */\r
279 /**\r
280 * Parses the response from the server\r
281 */\r
282 this.parse = function (command, data) {\r
d2d91c10 283 //console.log('gateway event', command, data);\r
ce13508b 284\r
696a66f8 285 if (command !== undefined) {\r
696a66f8
D
286 switch (command) {\r
287 case 'options':\r
288 $.each(data.options, function (name, value) {\r
289 switch (name) {\r
290 case 'CHANTYPES':\r
d9e06c6e 291 that.set('channel_prefix', value.join(''));\r
696a66f8
D
292 break;\r
293 case 'NETWORK':\r
294 that.set('name', value);\r
295 break;\r
296 case 'PREFIX':\r
297 that.set('user_prefixes', value);\r
298 break;\r
299 }\r
300 });\r
dff8edba 301 that.set('cap', data.cap);\r
696a66f8
D
302 break;\r
303\r
696a66f8
D
304 /*\r
305 case 'sync':\r
eaaf73b0
D
306 if (_kiwi.gateway.onSync && _kiwi.gateway.syncing) {\r
307 _kiwi.gateway.syncing = false;\r
308 _kiwi.gateway.onSync(item);\r
696a66f8
D
309 }\r
310 break;\r
311 */\r
312\r
313 case 'kiwi':\r
eaaf73b0 314 this.emit('_kiwi.' + data.namespace, data.data);\r
696a66f8
D
315 break;\r
316 }\r
317 }\r
ce13508b
D
318\r
319\r
320 if (typeof data.server !== 'undefined') {\r
321 that.trigger('connection:' + data.server.toString(), {\r
322 event_name: command,\r
323 event_data: data\r
324 });\r
325 }\r
fc9b83de
D
326\r
327 // Trigger the global events (Mainly legacy now)\r
328 that.trigger('on' + command, data);\r
696a66f8
D
329 };\r
330\r
331 /**\r
332 * Sends data to the server\r
333 * @private\r
334 * @param {Object} data The data to send\r
335 * @param {Function} callback A callback function\r
336 */\r
e7d65587
D
337 this.sendData = function (connection_id, data, callback) {\r
338 if (typeof connection_id === 'undefined' || connection_id === null)\r
339 connection_id = _kiwi.app.connections.active_connection.get('connection_id');\r
340\r
2ffd1291 341 var data_buffer = {\r
e7d65587 342 server: connection_id,\r
2ffd1291
D
343 data: JSON.stringify(data)\r
344 };\r
d99e7823 345 this.rpc.call('irc', data_buffer, callback);\r
696a66f8
D
346 };\r
347\r
348 /**\r
349 * Sends a PRIVMSG message\r
350 * @param {String} target The target of the message (e.g. a channel or nick)\r
351 * @param {String} msg The message to send\r
352 * @param {Function} callback A callback function\r
353 */\r
e7d65587 354 this.privmsg = function (connection_id, target, msg, callback) {\r
696a66f8
D
355 var data = {\r
356 method: 'privmsg',\r
357 args: {\r
358 target: target,\r
359 msg: msg\r
360 }\r
361 };\r
362\r
e7d65587 363 this.sendData(connection_id, data, callback);\r
696a66f8
D
364 };\r
365\r
366 /**\r
367 * Sends a NOTICE message\r
368 * @param {String} target The target of the message (e.g. a channel or nick)\r
369 * @param {String} msg The message to send\r
370 * @param {Function} callback A callback function\r
371 */\r
e7d65587 372 this.notice = function (connection_id, target, msg, callback) {\r
696a66f8
D
373 var data = {\r
374 method: 'notice',\r
375 args: {\r
376 target: target,\r
377 msg: msg\r
378 }\r
379 };\r
380\r
e7d65587 381 this.sendData(connection_id, data, callback);\r
696a66f8
D
382 };\r
383\r
384 /**\r
385 * Sends a CTCP message\r
386 * @param {Boolean} request Indicates whether this is a CTCP request (true) or reply (false)\r
387 * @param {String} type The type of CTCP message, e.g. 'VERSION', 'TIME', 'PING' etc.\r
388 * @param {String} target The target of the message, e.g a channel or nick\r
389 * @param {String} params Additional paramaters\r
390 * @param {Function} callback A callback function\r
391 */\r
e7d65587 392 this.ctcp = function (connection_id, request, type, target, params, callback) {\r
696a66f8
D
393 var data = {\r
394 method: 'ctcp',\r
395 args: {\r
396 request: request,\r
397 type: type,\r
398 target: target,\r
399 params: params\r
400 }\r
401 };\r
402\r
e7d65587 403 this.sendData(connection_id, data, callback);\r
696a66f8
D
404 };\r
405\r
406 /**\r
407 * @param {String} target The target of the message (e.g. a channel or nick)\r
408 * @param {String} msg The message to send\r
409 * @param {Function} callback A callback function\r
410 */\r
e7d65587 411 this.action = function (connection_id, target, msg, callback) {\r
11177392 412 this.ctcp(connection_id, true, 'ACTION', target, msg, callback);\r
696a66f8
D
413 };\r
414\r
415 /**\r
416 * Joins a channel\r
417 * @param {String} channel The channel to join\r
418 * @param {String} key The key to the channel\r
419 * @param {Function} callback A callback function\r
420 */\r
e7d65587 421 this.join = function (connection_id, channel, key, callback) {\r
696a66f8
D
422 var data = {\r
423 method: 'join',\r
424 args: {\r
425 channel: channel,\r
426 key: key\r
427 }\r
428 };\r
429\r
e7d65587 430 this.sendData(connection_id, data, callback);\r
696a66f8
D
431 };\r
432\r
72db27e4
D
433 /**\r
434 * Retrieves channel information\r
435 */\r
436 this.channelInfo = function (connection_id, channel, callback) {\r
437 var data = {\r
438 method: 'channel_info',\r
439 args: {\r
440 channel: channel\r
441 }\r
442 };\r
443\r
444 this.sendData(connection_id, data, callback);\r
445 };\r
446\r
696a66f8
D
447 /**\r
448 * Leaves a channel\r
449 * @param {String} channel The channel to part\r
450 * @param {Function} callback A callback function\r
451 */\r
e7d65587 452 this.part = function (connection_id, channel, callback) {\r
696a66f8
D
453 var data = {\r
454 method: 'part',\r
455 args: {\r
456 channel: channel\r
457 }\r
458 };\r
459\r
e7d65587 460 this.sendData(connection_id, data, callback);\r
696a66f8
D
461 };\r
462\r
463 /**\r
464 * Queries or modifies a channell topic\r
465 * @param {String} channel The channel to query or modify\r
466 * @param {String} new_topic The new topic to set\r
467 * @param {Function} callback A callback function\r
468 */\r
e7d65587 469 this.topic = function (connection_id, channel, new_topic, callback) {\r
696a66f8
D
470 var data = {\r
471 method: 'topic',\r
472 args: {\r
473 channel: channel,\r
474 topic: new_topic\r
475 }\r
476 };\r
477\r
e7d65587 478 this.sendData(connection_id, data, callback);\r
696a66f8
D
479 };\r
480\r
481 /**\r
482 * Kicks a user from a channel\r
483 * @param {String} channel The channel to kick the user from\r
484 * @param {String} nick The nick of the user to kick\r
485 * @param {String} reason The reason for kicking the user\r
486 * @param {Function} callback A callback function\r
487 */\r
e7d65587 488 this.kick = function (connection_id, channel, nick, reason, callback) {\r
696a66f8
D
489 var data = {\r
490 method: 'kick',\r
491 args: {\r
492 channel: channel,\r
493 nick: nick,\r
494 reason: reason\r
495 }\r
496 };\r
497\r
e7d65587 498 this.sendData(connection_id, data, callback);\r
696a66f8
D
499 };\r
500\r
501 /**\r
502 * Disconnects us from the server\r
503 * @param {String} msg The quit message to send to the IRC server\r
504 * @param {Function} callback A callback function\r
505 */\r
e7d65587 506 this.quit = function (connection_id, msg, callback) {\r
696a66f8
D
507 msg = msg || "";\r
508 var data = {\r
509 method: 'quit',\r
510 args: {\r
511 message: msg\r
512 }\r
513 };\r
514\r
e7d65587 515 this.sendData(connection_id, data, callback);\r
696a66f8
D
516 };\r
517\r
518 /**\r
519 * Sends a string unmodified to the IRC server\r
520 * @param {String} data The data to send to the IRC server\r
521 * @param {Function} callback A callback function\r
522 */\r
e7d65587 523 this.raw = function (connection_id, data, callback) {\r
696a66f8
D
524 data = {\r
525 method: 'raw',\r
526 args: {\r
527 data: data\r
528 }\r
529 };\r
530\r
e7d65587 531 this.sendData(connection_id, data, callback);\r
696a66f8
D
532 };\r
533\r
534 /**\r
535 * Changes our nickname\r
536 * @param {String} new_nick Our new nickname\r
537 * @param {Function} callback A callback function\r
538 */\r
e7d65587 539 this.changeNick = function (connection_id, new_nick, callback) {\r
696a66f8
D
540 var data = {\r
541 method: 'nick',\r
542 args: {\r
543 nick: new_nick\r
544 }\r
545 };\r
546\r
e7d65587 547 this.sendData(connection_id, data, callback);\r
696a66f8
D
548 };\r
549\r
72db27e4
D
550 /**\r
551 * Sets a mode for a target\r
552 */\r
553 this.mode = function (connection_id, target, mode_string, callback) {\r
554 data = {\r
555 method: 'raw',\r
556 args: {\r
557 data: 'MODE ' + target + ' ' + mode_string\r
558 }\r
559 };\r
560\r
561 this.sendData(connection_id, data, callback);\r
562 };\r
563\r
564\r
d1b3e8b3
VDF
565 /**\r
566 * Sends ENCODING change request to server.\r
567 * @param {String} new_encoding The new proposed encode\r
568 * @param {Fucntion} callback A callback function\r
569 */\r
570 this.setEncoding = function (connection_id, new_encoding, callback) {\r
65c5a477
VDF
571 var data = {\r
572 method: 'encoding',\r
573 args: {\r
574 encoding: new_encoding\r
575 }\r
576 };\r
577 this.sendData(connection_id, data, callback);\r
d1b3e8b3
VDF
578 };\r
579\r
696a66f8
D
580 /**\r
581 * Sends data to a fellow Kiwi IRC user\r
582 * @param {String} target The nick of the Kiwi IRC user to send to\r
583 * @param {String} data The data to send\r
584 * @param {Function} callback A callback function\r
585 */\r
586 this.kiwi = function (target, data, callback) {\r
587 data = {\r
588 method: 'kiwi',\r
589 args: {\r
590 target: target,\r
591 data: data\r
592 }\r
593 };\r
594\r
595 this.sendData(data, callback);\r
596 };\r
597\r
f3091277 598\r
696a66f8 599 return new (Backbone.Model.extend(this))(arguments);\r
d1b3e8b3 600};\r