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