1 _kiwi
.model
.Gateway = function () {
3 // Set to a reference to this object within initialize()
8 * The name of the network
14 * The address (URL) of the network
20 * The current nickname
26 * The channel prefix for this network
32 * The user prefixes for channel owner/admin/op/voice etc. on this network
35 user_prefixes
: ['~', '&', '@', '+'],
38 * The URL to the Kiwi server
41 kiwi_server
: '//kiwi',
44 * List of nicks we are ignoring
51 this.initialize = function () {
54 // For ease of access. The socket.io object
55 this.socket
= this.get('socket');
57 this.applyEventHandlers();
59 // Used to check if a disconnection was unplanned
60 this.disconnect_requested
= false;
64 this.applyEventHandlers = function () {
66 kiwi.gateway.on('message:#channel', my_function);
67 kiwi.gateway.on('message:somenick', my_function);
69 kiwi.gateway.on('notice:#channel', my_function);
70 kiwi.gateway.on('action:somenick', my_function);
72 kiwi.gateway.on('join:#channel', my_function);
73 kiwi.gateway.on('part:#channel', my_function);
74 kiwi.gateway.on('quit', my_function);
78 // Some easier handler events
79 this.on('onmsg', function (event
) {
81 connection
= _kiwi
.app
.connections
.getByConnectionId(event
.server
),
82 is_pm
= (event
.channel
== connection
.get('nick'));
84 source
= is_pm
? event
.nick
: event
.channel
;
86 that
.trigger('message:' + source
, event
);
87 that
.trigger('message', event
);
90 that
.trigger('pm:' + source
, event
);
91 that
.trigger('pm', event
);
96 this.on('onnotice', function (event
) {
97 // The notice towards a channel or a query window?
98 var source
= event
.target
|| event
.nick
;
100 this.trigger('notice:' + source
, event
);
101 this.trigger('notice', event
);
105 this.on('onaction', function (event
) {
107 connection
= _kiwi
.app
.connections
.getByConnectionId(event
.server
),
108 is_pm
= (event
.channel
== connection
.get('nick'));
110 source
= is_pm
? event
.nick
: event
.channel
;
112 that
.trigger('action:' + source
, event
);
115 that
.trigger('action:' + source
, event
);
116 that
.trigger('action', event
);
121 this.on('ontopic', function (event
) {
122 that
.trigger('topic:' + event
.channel
, event
);
123 that
.trigger('topic', event
);
127 this.on('onjoin', function (event
) {
128 that
.trigger('join:' + event
.channel
, event
);
129 that
.trigger('join', event
);
136 this.reconnect = function (callback
) {
140 this.disconnect_requested
= true;
141 this.socket
.disconnect();
143 // To get around the allow-origin issues for requests, completely reload the
144 // transport source from the new server
147 // Path to get the socket.io transport code
148 transport_path
= _kiwi
.app
.kiwi_server
+ _kiwi
.app
.get('base_path') + '/transport/socket.io.js?ts='+(new Date().getTime());
149 $script(transport_path
, function() {
151 return callback('err_kiwi_server_not_found');
154 that
.set('kiwi_server', _kiwi
.app
.kiwi_server
+ '/kiwi');
155 that
.connect(callback
);
162 * Connects to the server
163 * @param {Function} callback A callback function to be invoked once Kiwi's server has connected to the IRC server
165 this.connect = function (callback
) {
168 // Work out the resource URL for socket.io
169 if (_kiwi
.app
.get('base_path').substr(0, 1) === '/') {
170 resource
= _kiwi
.app
.get('base_path');
171 resource
= resource
.substr(1, resource
.length
-1);
172 resource
+= '/transport';
174 resource
= _kiwi
.app
.get('base_path') + '/transport';
177 this.socket
= io
.connect(this.get('kiwi_server'), {
178 'resource': resource
,
180 'try multiple transports': true,
181 'connect timeout': 3000,
182 'max reconnection attempts': 7,
183 'reconnection delay': 2000,
184 'sync disconnect on unload': false
186 this.socket
.on('connect_failed', function (reason
) {
187 this.socket
.disconnect();
188 this.trigger("connect_fail", {reason
: reason
});
191 this.socket
.on('error', function (e
) {
192 console
.log("_kiwi.gateway.socket.on('error')", {reason
: e
});
193 that
.trigger("connect_fail", {reason
: e
});
196 this.socket
.on('connecting', function (transport_type
) {
197 console
.log("_kiwi.gateway.socket.on('connecting')");
198 that
.trigger("connecting");
202 * Once connected to the kiwi server send the IRC connect command along
203 * with the IRC server details.
204 * A `connect` event is sent from the kiwi server once connected to the
205 * IRCD and the nick has been accepted.
207 this.socket
.on('connect', function () {
208 // Reset the disconnect_requested flag
209 that
.disconnect_requested
= false;
211 callback
&& callback();
214 this.socket
.on('too_many_connections', function () {
215 that
.trigger("connect_fail", {reason
: 'too_many_connections'});
218 this.socket
.on('irc', function (data
, callback
) {
219 that
.parse(data
.command
, data
.data
);
222 this.socket
.on('kiwi', function (data
, callback
) {
223 that
.parseKiwi(data
.command
, data
.data
);
226 this.socket
.on('disconnect', function () {
227 that
.trigger("disconnect", {});
228 console
.log("_kiwi.gateway.socket.on('disconnect')");
231 this.socket
.on('close', function () {
232 console
.log("_kiwi.gateway.socket.on('close')");
235 this.socket
.on('reconnecting', function (reconnectionDelay
, reconnectionAttempts
) {
236 console
.log("_kiwi.gateway.socket.on('reconnecting')");
237 that
.trigger("reconnecting", {delay
: reconnectionDelay
, attempts
: reconnectionAttempts
});
240 this.socket
.on('reconnect_failed', function () {
241 console
.log("_kiwi.gateway.socket.on('reconnect_failed')");
247 * Return a new network object with the new connection details
249 this.newConnection = function(connection_info
, callback_fn
) {
252 this.makeIrcConnection(connection_info
, function(err
, server_num
) {
256 if (!_kiwi
.app
.connections
.getByConnectionId(server_num
)){
258 connection_id
: server_num
,
259 nick
: connection_info
.nick
,
260 address
: connection_info
.host
,
261 port
: connection_info
.port
,
262 ssl
: connection_info
.ssl
,
263 password
: connection_info
.password
265 connection
= new _kiwi
.model
.Network(inf
);
266 _kiwi
.app
.connections
.add(connection
);
269 console
.log("_kiwi.gateway.socket.on('connect')", connection
);
270 callback_fn
&& callback_fn(err
, connection
);
273 console
.log("_kiwi.gateway.socket.on('error')", {reason
: err
});
274 callback_fn
&& callback_fn(err
);
281 * Make a new IRC connection and return its connection ID
283 this.makeIrcConnection = function(connection_info
, callback_fn
) {
286 nick
: connection_info
.nick
,
287 hostname
: connection_info
.host
,
288 port
: connection_info
.port
,
289 ssl
: connection_info
.ssl
,
290 password
: connection_info
.password
293 // A few optional parameters
294 if (connection_info
.options
.encoding
)
295 server_info
.encoding
= connection_info
.options
.encoding
;
297 this.socket
.emit('kiwi', server_info
, function (err
, server_num
) {
299 callback_fn
&& callback_fn(err
, server_num
);
302 callback_fn
&& callback_fn(err
);
308 this.isConnected = function () {
309 return this.socket
.socket
.connected
;
314 this.parseKiwi = function (command
, data
) {
315 this.trigger('kiwi:' + command
, data
);
316 this.trigger('kiwi', data
);
338 * Parses the response from the server
340 this.parse = function (command
, data
) {
341 //console.log('gateway event', command, data);
343 if (command
!== undefined) {
346 $.each(data
.options
, function (name
, value
) {
349 that
.set('channel_prefix', value
.join(''));
352 that
.set('name', value
);
355 that
.set('user_prefixes', value
);
359 that
.set('cap', data
.cap
);
364 if (_kiwi.gateway.onSync && _kiwi.gateway.syncing) {
365 _kiwi.gateway.syncing = false;
366 _kiwi.gateway.onSync(item);
372 this.emit('_kiwi.' + data
.namespace, data
.data
);
378 if (typeof data
.server
!== 'undefined') {
379 that
.trigger('connection:' + data
.server
.toString(), {
385 // Trigger the global events (Mainly legacy now)
386 that
.trigger('on' + command
, data
);
390 * Sends data to the server
392 * @param {Object} data The data to send
393 * @param {Function} callback A callback function
395 this.sendData = function (connection_id
, data
, callback
) {
396 if (typeof connection_id
=== 'undefined' || connection_id
=== null)
397 connection_id
= _kiwi
.app
.connections
.active_connection
.get('connection_id');
400 server
: connection_id
,
401 data
: JSON
.stringify(data
)
403 this.socket
.emit('irc', data_buffer
, callback
);
407 * Sends a PRIVMSG message
408 * @param {String} target The target of the message (e.g. a channel or nick)
409 * @param {String} msg The message to send
410 * @param {Function} callback A callback function
412 this.privmsg = function (connection_id
, target
, msg
, callback
) {
421 this.sendData(connection_id
, data
, callback
);
425 * Sends a NOTICE message
426 * @param {String} target The target of the message (e.g. a channel or nick)
427 * @param {String} msg The message to send
428 * @param {Function} callback A callback function
430 this.notice = function (connection_id
, target
, msg
, callback
) {
439 this.sendData(connection_id
, data
, callback
);
443 * Sends a CTCP message
444 * @param {Boolean} request Indicates whether this is a CTCP request (true) or reply (false)
445 * @param {String} type The type of CTCP message, e.g. 'VERSION', 'TIME', 'PING' etc.
446 * @param {String} target The target of the message, e.g a channel or nick
447 * @param {String} params Additional paramaters
448 * @param {Function} callback A callback function
450 this.ctcp = function (connection_id
, request
, type
, target
, params
, callback
) {
461 this.sendData(connection_id
, data
, callback
);
465 * @param {String} target The target of the message (e.g. a channel or nick)
466 * @param {String} msg The message to send
467 * @param {Function} callback A callback function
469 this.action = function (connection_id
, target
, msg
, callback
) {
470 this.ctcp(connection_id
, true, 'ACTION', target
, msg
, callback
);
475 * @param {String} channel The channel to join
476 * @param {String} key The key to the channel
477 * @param {Function} callback A callback function
479 this.join = function (connection_id
, channel
, key
, callback
) {
488 this.sendData(connection_id
, data
, callback
);
493 * @param {String} channel The channel to part
494 * @param {Function} callback A callback function
496 this.part = function (connection_id
, channel
, callback
) {
504 this.sendData(connection_id
, data
, callback
);
508 * Queries or modifies a channell topic
509 * @param {String} channel The channel to query or modify
510 * @param {String} new_topic The new topic to set
511 * @param {Function} callback A callback function
513 this.topic = function (connection_id
, channel
, new_topic
, callback
) {
522 this.sendData(connection_id
, data
, callback
);
526 * Kicks a user from a channel
527 * @param {String} channel The channel to kick the user from
528 * @param {String} nick The nick of the user to kick
529 * @param {String} reason The reason for kicking the user
530 * @param {Function} callback A callback function
532 this.kick = function (connection_id
, channel
, nick
, reason
, callback
) {
542 this.sendData(connection_id
, data
, callback
);
546 * Disconnects us from the server
547 * @param {String} msg The quit message to send to the IRC server
548 * @param {Function} callback A callback function
550 this.quit = function (connection_id
, msg
, callback
) {
559 this.sendData(connection_id
, data
, callback
);
563 * Sends a string unmodified to the IRC server
564 * @param {String} data The data to send to the IRC server
565 * @param {Function} callback A callback function
567 this.raw = function (connection_id
, data
, callback
) {
575 this.sendData(connection_id
, data
, callback
);
579 * Changes our nickname
580 * @param {String} new_nick Our new nickname
581 * @param {Function} callback A callback function
583 this.changeNick = function (connection_id
, new_nick
, callback
) {
591 this.sendData(connection_id
, data
, callback
);
595 * Sends ENCODING change request to server.
596 * @param {String} new_encoding The new proposed encode
597 * @param {Fucntion} callback A callback function
599 this.setEncoding = function (connection_id
, new_encoding
, callback
) {
603 encoding
: new_encoding
606 this.sendData(connection_id
, data
, callback
);
610 * Sends data to a fellow Kiwi IRC user
611 * @param {String} target The nick of the Kiwi IRC user to send to
612 * @param {String} data The data to send
613 * @param {Function} callback A callback function
615 this.kiwi = function (target
, data
, callback
) {
624 this.sendData(data
, callback
);
627 // Check a nick alongside our ignore list
628 this.isNickIgnored = function (nick
) {
629 var idx
, list
= this.get('ignore_list');
632 for (idx
= 0; idx
< list
.length
; idx
++) {
633 pattern
= list
[idx
].replace(/([.+^$[\]\\(){}|-])/g, "\\$1")
637 regex
= new RegExp(pattern
, 'i');
638 if (regex
.test(nick
)) return true;
645 return new (Backbone
.Model
.extend(this))(arguments
);