Merge branch 'development'
[KiwiIRC.git] / client / assets / dev / model_gateway.js
1 _kiwi.model.Gateway = function () {
2
3 // Set to a reference to this object within initialize()
4 var that = null;
5
6 this.defaults = {
7 /**
8 * The name of the network
9 * @type String
10 */
11 name: 'Server',
12
13 /**
14 * The address (URL) of the network
15 * @type String
16 */
17 address: '',
18
19 /**
20 * The current nickname
21 * @type String
22 */
23 nick: '',
24
25 /**
26 * The channel prefix for this network
27 * @type String
28 */
29 channel_prefix: '#',
30
31 /**
32 * The user prefixes for channel owner/admin/op/voice etc. on this network
33 * @type Array
34 */
35 user_prefixes: ['~', '&', '@', '+'],
36
37 /**
38 * The URL to the Kiwi server
39 * @type String
40 */
41 kiwi_server: '//kiwi'
42 };
43
44
45 this.initialize = function () {
46 that = this;
47
48 // For ease of access. The socket.io object
49 this.socket = this.get('socket');
50 };
51
52
53 /**
54 * Connects to the server
55 * @param {String} host The hostname or IP address of the IRC server to connect to
56 * @param {Number} port The port of the IRC server to connect to
57 * @param {Boolean} ssl Whether or not to connect to the IRC server using SSL
58 * @param {String} password The password to supply to the IRC server during registration
59 * @param {Function} callback A callback function to be invoked once Kiwi's server has connected to the IRC server
60 */
61 this.connect = function (host, port, ssl, password, callback) {
62 var resource;
63
64 // Work out the resource URL for socket.io
65 if (_kiwi.app.get('base_path').substr(0, 1) === '/') {
66 resource = _kiwi.app.get('base_path');
67 resource = resource.substr(1, resource.length-1);
68 resource += '/transport';
69 } else {
70 resource = _kiwi.app.get('base_path') + '/transport';
71 }
72
73 this.socket = io.connect(this.get('kiwi_server'), {
74 'resource': resource,
75
76 'try multiple transports': true,
77 'connect timeout': 3000,
78 'max reconnection attempts': 7,
79 'reconnection delay': 2000,
80 'sync disconnect on unload': false
81 });
82 this.socket.on('connect_failed', function (reason) {
83 this.socket.disconnect();
84 this.trigger("connect_fail", {reason: reason});
85 });
86
87 this.socket.on('error', function (e) {
88 console.log("_kiwi.gateway.socket.on('error')", {reason: e});
89 that.trigger("connect_fail", {reason: e});
90 });
91
92 this.socket.on('connecting', function (transport_type) {
93 console.log("_kiwi.gateway.socket.on('connecting')");
94 that.trigger("connecting");
95 });
96
97 /**
98 * Once connected to the kiwi server send the IRC connect command along
99 * with the IRC server details.
100 * A `connect` event is sent from the kiwi server once connected to the
101 * IRCD and the nick has been accepted.
102 */
103 this.socket.on('connect', function () {
104 this.emit('kiwi', {command: 'connect', nick: that.get('nick'), hostname: host, port: port, ssl: ssl, password:password}, function (err, server_num) {
105 if (!err) {
106 that.server_num = server_num;
107 console.log("_kiwi.gateway.socket.on('connect')");
108 } else {
109 console.log("_kiwi.gateway.socket.on('error')", {reason: err});
110 callback(err);
111 }
112 });
113 });
114
115 this.socket.on('too_many_connections', function () {
116 that.trigger("connect_fail", {reason: 'too_many_connections'});
117 });
118
119 this.socket.on('irc', function (data, callback) {
120 that.parse(data.command, data.data);
121 });
122
123 this.socket.on('kiwi', function (data, callback) {
124 that.parseKiwi(data.command, data.data);
125 });
126
127 this.socket.on('disconnect', function () {
128 that.trigger("disconnect", {});
129 console.log("_kiwi.gateway.socket.on('disconnect')");
130 });
131
132 this.socket.on('close', function () {
133 console.log("_kiwi.gateway.socket.on('close')");
134 });
135
136 this.socket.on('reconnecting', function (reconnectionDelay, reconnectionAttempts) {
137 console.log("_kiwi.gateway.socket.on('reconnecting')");
138 that.trigger("reconnecting", {delay: reconnectionDelay, attempts: reconnectionAttempts});
139 });
140
141 this.socket.on('reconnect_failed', function () {
142 console.log("_kiwi.gateway.socket.on('reconnect_failed')");
143 });
144 };
145
146
147
148 this.isConnected = function () {
149 return this.socket.socket.connected;
150 };
151
152
153
154 this.parseKiwi = function (command, data) {
155 console.log('kiwi event', command, data);
156 };
157 /*
158 Events:
159 msg
160 action
161 server_connect
162 options
163 motd
164 notice
165 userlist
166 nick
167 join
168 topic
169 part
170 kick
171 quit
172 whois
173 syncchannel_redirect
174 debug
175 */
176 /**
177 * Parses the response from the server
178 */
179 this.parse = function (command, data) {
180 //console.log('gateway event', command, data);
181 if (command !== undefined) {
182 that.trigger('on' + command, data);
183
184 switch (command) {
185 case 'options':
186 $.each(data.options, function (name, value) {
187 switch (name) {
188 case 'CHANTYPES':
189 // TODO: Check this. Why is it only getting the first char?
190 that.set('channel_prefix', value.join('').charAt(0));
191 break;
192 case 'NETWORK':
193 that.set('name', value);
194 break;
195 case 'PREFIX':
196 that.set('user_prefixes', value);
197 break;
198 }
199 });
200 that.set('cap', data.cap);
201 break;
202
203 case 'connect':
204 that.set('nick', data.nick);
205 break;
206
207 case 'nick':
208 if (data.nick === that.get('nick')) {
209 that.set('nick', data.newnick);
210 }
211 break;
212 /*
213 case 'sync':
214 if (_kiwi.gateway.onSync && _kiwi.gateway.syncing) {
215 _kiwi.gateway.syncing = false;
216 _kiwi.gateway.onSync(item);
217 }
218 break;
219 */
220
221 case 'kiwi':
222 this.emit('_kiwi.' + data.namespace, data.data);
223 break;
224 }
225 }
226 };
227
228 /**
229 * Sends data to the server
230 * @private
231 * @param {Object} data The data to send
232 * @param {Function} callback A callback function
233 */
234 this.sendData = function (data, callback) {
235 this.socket.emit('irc', {server: 0, data: JSON.stringify(data)}, callback);
236 };
237
238 /**
239 * Sends a PRIVMSG message
240 * @param {String} target The target of the message (e.g. a channel or nick)
241 * @param {String} msg The message to send
242 * @param {Function} callback A callback function
243 */
244 this.privmsg = function (target, msg, callback) {
245 var data = {
246 method: 'privmsg',
247 args: {
248 target: target,
249 msg: msg
250 }
251 };
252
253 this.sendData(data, callback);
254 };
255
256 /**
257 * Sends a NOTICE message
258 * @param {String} target The target of the message (e.g. a channel or nick)
259 * @param {String} msg The message to send
260 * @param {Function} callback A callback function
261 */
262 this.notice = function (target, msg, callback) {
263 var data = {
264 method: 'notice',
265 args: {
266 target: target,
267 msg: msg
268 }
269 };
270
271 this.sendData(data, callback);
272 };
273
274 /**
275 * Sends a CTCP message
276 * @param {Boolean} request Indicates whether this is a CTCP request (true) or reply (false)
277 * @param {String} type The type of CTCP message, e.g. 'VERSION', 'TIME', 'PING' etc.
278 * @param {String} target The target of the message, e.g a channel or nick
279 * @param {String} params Additional paramaters
280 * @param {Function} callback A callback function
281 */
282 this.ctcp = function (request, type, target, params, callback) {
283 var data = {
284 method: 'ctcp',
285 args: {
286 request: request,
287 type: type,
288 target: target,
289 params: params
290 }
291 };
292
293 this.sendData(data, callback);
294 };
295
296 /**
297 * @param {String} target The target of the message (e.g. a channel or nick)
298 * @param {String} msg The message to send
299 * @param {Function} callback A callback function
300 */
301 this.action = function (target, msg, callback) {
302 this.ctcp(true, 'ACTION', target, msg, callback);
303 };
304
305 /**
306 * Joins a channel
307 * @param {String} channel The channel to join
308 * @param {String} key The key to the channel
309 * @param {Function} callback A callback function
310 */
311 this.join = function (channel, key, callback) {
312 var data = {
313 method: 'join',
314 args: {
315 channel: channel,
316 key: key
317 }
318 };
319
320 this.sendData(data, callback);
321 };
322
323 /**
324 * Leaves a channel
325 * @param {String} channel The channel to part
326 * @param {Function} callback A callback function
327 */
328 this.part = function (channel, callback) {
329 var data = {
330 method: 'part',
331 args: {
332 channel: channel
333 }
334 };
335
336 this.sendData(data, callback);
337 };
338
339 /**
340 * Queries or modifies a channell topic
341 * @param {String} channel The channel to query or modify
342 * @param {String} new_topic The new topic to set
343 * @param {Function} callback A callback function
344 */
345 this.topic = function (channel, new_topic, callback) {
346 var data = {
347 method: 'topic',
348 args: {
349 channel: channel,
350 topic: new_topic
351 }
352 };
353
354 this.sendData(data, callback);
355 };
356
357 /**
358 * Kicks a user from a channel
359 * @param {String} channel The channel to kick the user from
360 * @param {String} nick The nick of the user to kick
361 * @param {String} reason The reason for kicking the user
362 * @param {Function} callback A callback function
363 */
364 this.kick = function (channel, nick, reason, callback) {
365 var data = {
366 method: 'kick',
367 args: {
368 channel: channel,
369 nick: nick,
370 reason: reason
371 }
372 };
373
374 this.sendData(data, callback);
375 };
376
377 /**
378 * Disconnects us from the server
379 * @param {String} msg The quit message to send to the IRC server
380 * @param {Function} callback A callback function
381 */
382 this.quit = function (msg, callback) {
383 msg = msg || "";
384 var data = {
385 method: 'quit',
386 args: {
387 message: msg
388 }
389 };
390
391 this.sendData(data, callback);
392 };
393
394 /**
395 * Sends a string unmodified to the IRC server
396 * @param {String} data The data to send to the IRC server
397 * @param {Function} callback A callback function
398 */
399 this.raw = function (data, callback) {
400 data = {
401 method: 'raw',
402 args: {
403 data: data
404 }
405 };
406
407 this.sendData(data, callback);
408 };
409
410 /**
411 * Changes our nickname
412 * @param {String} new_nick Our new nickname
413 * @param {Function} callback A callback function
414 */
415 this.changeNick = function (new_nick, callback) {
416 var data = {
417 method: 'nick',
418 args: {
419 nick: new_nick
420 }
421 };
422
423 this.sendData(data, callback);
424 };
425
426 /**
427 * Sends data to a fellow Kiwi IRC user
428 * @param {String} target The nick of the Kiwi IRC user to send to
429 * @param {String} data The data to send
430 * @param {Function} callback A callback function
431 */
432 this.kiwi = function (target, data, callback) {
433 data = {
434 method: 'kiwi',
435 args: {
436 target: target,
437 data: data
438 }
439 };
440
441 this.sendData(data, callback);
442 };
443
444
445 return new (Backbone.Model.extend(this))(arguments);
446 };