Merge with development branch (New server codebase)
[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 break;
201
202 case 'connect':
203 that.set('nick', data.nick);
204 break;
205
206 case 'nick':
207 if (data.nick === that.get('nick')) {
208 that.set('nick', data.newnick);
209 }
210 break;
211 /*
212 case 'sync':
213 if (kiwi.gateway.onSync && kiwi.gateway.syncing) {
214 kiwi.gateway.syncing = false;
215 kiwi.gateway.onSync(item);
216 }
217 break;
218 */
219
220 case 'kiwi':
221 this.emit('kiwi.' + data.namespace, data.data);
222 break;
223 }
224 }
225 };
226
227 /**
228 * Sends data to the server
229 * @private
230 * @param {Object} data The data to send
231 * @param {Function} callback A callback function
232 */
233 this.sendData = function (data, callback) {
234 this.socket.emit('irc', {server: 0, data: JSON.stringify(data)}, callback);
235 };
236
237 /**
238 * Sends a PRIVMSG message
239 * @param {String} target The target of the message (e.g. a channel or nick)
240 * @param {String} msg The message to send
241 * @param {Function} callback A callback function
242 */
243 this.privmsg = function (target, msg, callback) {
244 var data = {
245 method: 'privmsg',
246 args: {
247 target: target,
248 msg: msg
249 }
250 };
251
252 this.sendData(data, callback);
253 };
254
255 /**
256 * Sends a NOTICE message
257 * @param {String} target The target of the message (e.g. a channel or nick)
258 * @param {String} msg The message to send
259 * @param {Function} callback A callback function
260 */
261 this.notice = function (target, msg, callback) {
262 var data = {
263 method: 'notice',
264 args: {
265 target: target,
266 msg: msg
267 }
268 };
269
270 this.sendData(data, callback);
271 };
272
273 /**
274 * Sends a CTCP message
275 * @param {Boolean} request Indicates whether this is a CTCP request (true) or reply (false)
276 * @param {String} type The type of CTCP message, e.g. 'VERSION', 'TIME', 'PING' etc.
277 * @param {String} target The target of the message, e.g a channel or nick
278 * @param {String} params Additional paramaters
279 * @param {Function} callback A callback function
280 */
281 this.ctcp = function (request, type, target, params, callback) {
282 var data = {
283 method: 'ctcp',
284 args: {
285 request: request,
286 type: type,
287 target: target,
288 params: params
289 }
290 };
291
292 this.sendData(data, callback);
293 };
294
295 /**
296 * @param {String} target The target of the message (e.g. a channel or nick)
297 * @param {String} msg The message to send
298 * @param {Function} callback A callback function
299 */
300 this.action = function (target, msg, callback) {
301 this.ctcp(true, 'ACTION', target, msg, callback);
302 };
303
304 /**
305 * Joins a channel
306 * @param {String} channel The channel to join
307 * @param {String} key The key to the channel
308 * @param {Function} callback A callback function
309 */
310 this.join = function (channel, key, callback) {
311 var data = {
312 method: 'join',
313 args: {
314 channel: channel,
315 key: key
316 }
317 };
318
319 this.sendData(data, callback);
320 };
321
322 /**
323 * Leaves a channel
324 * @param {String} channel The channel to part
325 * @param {Function} callback A callback function
326 */
327 this.part = function (channel, callback) {
328 var data = {
329 method: 'part',
330 args: {
331 channel: channel
332 }
333 };
334
335 this.sendData(data, callback);
336 };
337
338 /**
339 * Queries or modifies a channell topic
340 * @param {String} channel The channel to query or modify
341 * @param {String} new_topic The new topic to set
342 * @param {Function} callback A callback function
343 */
344 this.topic = function (channel, new_topic, callback) {
345 var data = {
346 method: 'topic',
347 args: {
348 channel: channel,
349 topic: new_topic
350 }
351 };
352
353 this.sendData(data, callback);
354 };
355
356 /**
357 * Kicks a user from a channel
358 * @param {String} channel The channel to kick the user from
359 * @param {String} nick The nick of the user to kick
360 * @param {String} reason The reason for kicking the user
361 * @param {Function} callback A callback function
362 */
363 this.kick = function (channel, nick, reason, callback) {
364 var data = {
365 method: 'kick',
366 args: {
367 channel: channel,
368 nick: nick,
369 reason: reason
370 }
371 };
372
373 this.sendData(data, callback);
374 };
375
376 /**
377 * Disconnects us from the server
378 * @param {String} msg The quit message to send to the IRC server
379 * @param {Function} callback A callback function
380 */
381 this.quit = function (msg, callback) {
382 msg = msg || "";
383 var data = {
384 method: 'quit',
385 args: {
386 message: msg
387 }
388 };
389
390 this.sendData(data, callback);
391 };
392
393 /**
394 * Sends a string unmodified to the IRC server
395 * @param {String} data The data to send to the IRC server
396 * @param {Function} callback A callback function
397 */
398 this.raw = function (data, callback) {
399 data = {
400 method: 'raw',
401 args: {
402 data: data
403 }
404 };
405
406 this.sendData(data, callback);
407 };
408
409 /**
410 * Changes our nickname
411 * @param {String} new_nick Our new nickname
412 * @param {Function} callback A callback function
413 */
414 this.changeNick = function (new_nick, callback) {
415 var data = {
416 method: 'nick',
417 args: {
418 nick: new_nick
419 }
420 };
421
422 this.sendData(data, callback);
423 };
424
425 /**
426 * Sends data to a fellow Kiwi IRC user
427 * @param {String} target The nick of the Kiwi IRC user to send to
428 * @param {String} data The data to send
429 * @param {Function} callback A callback function
430 */
431 this.kiwi = function (target, data, callback) {
432 data = {
433 method: 'kiwi',
434 args: {
435 target: target,
436 data: data
437 }
438 };
439
440 this.sendData(data, callback);
441 };
442
443
444 return new (Backbone.Model.extend(this))(arguments);
445 };