Merge branch 'i18n' into development
[KiwiIRC.git] / server / irc / commands.js
1 var _ = require('lodash'),
2 irc_numerics,
3 IrcCommands,
4 handlers,
5 unknownCommand;
6
7 irc_numerics = {
8 '001': 'RPL_WELCOME',
9 '004': 'RPL_MYINFO',
10 '005': 'RPL_ISUPPORT',
11 '006': 'RPL_MAPMORE',
12 '007': 'RPL_MAPEND',
13 '250': 'RPL_STATSCONN',
14 '251': 'RPL_LUSERCLIENT',
15 '252': 'RPL_LUSEROP',
16 '253': 'RPL_LUSERUNKNOWN',
17 '254': 'RPL_LUSERCHANNELS',
18 '255': 'RPL_LUSERME',
19 '265': 'RPL_LOCALUSERS',
20 '266': 'RPL_GLOBALUSERS',
21 '301': 'RPL_AWAY',
22 '307': 'RPL_WHOISREGNICK',
23 '311': 'RPL_WHOISUSER',
24 '312': 'RPL_WHOISSERVER',
25 '313': 'RPL_WHOISOPERATOR',
26 '314': 'RPL_WHOWASUSER',
27 '317': 'RPL_WHOISIDLE',
28 '318': 'RPL_ENDOFWHOIS',
29 '319': 'RPL_WHOISCHANNELS',
30 '321': 'RPL_LISTSTART',
31 '322': 'RPL_LIST',
32 '323': 'RPL_LISTEND',
33 '331': 'RPL_NOTOPIC',
34 '332': 'RPL_TOPIC',
35 '333': 'RPL_TOPICWHOTIME',
36 '353': 'RPL_NAMEREPLY',
37 '364': 'RPL_LINKS',
38 '365': 'RPL_ENDOFLINKS',
39 '366': 'RPL_ENDOFNAMES',
40 '367': 'RPL_BANLIST',
41 '368': 'RPL_ENDOFBANLIST',
42 '369': 'RPL_ENDOFWHOWAS',
43 '372': 'RPL_MOTD',
44 '375': 'RPL_MOTDSTART',
45 '376': 'RPL_ENDOFMOTD',
46 '379': 'RPL_WHOISMODES',
47 '401': 'ERR_NOSUCHNICK',
48 '404': 'ERR_CANNOTSENDTOCHAN',
49 '405': 'ERR_TOOMANYCHANNELS',
50 '406': 'ERR_WASNOSUCHNICK',
51 '421': 'ERR_UNKNOWNCOMMAND',
52 '422': 'ERR_NOMOTD',
53 '432': 'ERR_ERRONEUSNICKNAME',
54 '433': 'ERR_NICKNAMEINUSE',
55 '441': 'ERR_USERNOTINCHANNEL',
56 '442': 'ERR_NOTONCHANNEL',
57 '451': 'ERR_NOTREGISTERED',
58 '464': 'ERR_PASSWDMISMATCH',
59 '470': 'ERR_LINKCHANNEL',
60 '471': 'ERR_CHANNELISFULL',
61 '473': 'ERR_INVITEONLYCHAN',
62 '474': 'ERR_BANNEDFROMCHAN',
63 '475': 'ERR_BADCHANNELKEY',
64 '481': 'ERR_NOPRIVILEGES',
65 '482': 'ERR_CHANOPRIVSNEEDED',
66 '670': 'RPL_STARTTLS',
67 '900': 'RPL_SASLAUTHENTICATED',
68 '903': 'RPL_SASLLOGGEDIN',
69 '904': 'ERR_SASLNOTAUTHORISED',
70 '906': 'ERR_SASLABORTED',
71 '907': 'ERR_SASLALREADYAUTHED'
72 };
73
74
75 IrcCommands = function (irc_connection, con_num, client) {
76 this.irc_connection = irc_connection;
77 this.con_num = con_num;
78 this.client = client;
79 };
80 module.exports = IrcCommands;
81
82 IrcCommands.prototype.dispatch = function (command, data) {
83 command += '';
84 if (irc_numerics[command]) {
85 command = irc_numerics[command];
86 }
87 if (handlers[command]) {
88 handlers[command].call(this, data);
89 } else {
90 unknownCommand(command, data);
91 }
92 };
93
94 IrcCommands.addHandler = function (command, handler) {
95 if (typeof handler !== 'function') {
96 return false;
97 }
98 handlers[command] = handler;
99 };
100
101 IrcCommands.addNumeric = function (numeric, handler_name) {
102 irc_numerics[numeric + ''] = handler_name +'';
103 };
104
105 unknownCommand = function (command, data) {
106 // TODO: Do something here, log?
107 };
108
109
110 handlers = {
111 'RPL_WELCOME': function (command) {
112 var nick = command.params[0];
113 this.irc_connection.registered = true;
114 this.cap_negotation = false;
115 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' connect', {
116 nick: nick
117 });
118 },
119
120 'RPL_ISUPPORT': function (command) {
121 var options, i, option, matches, j;
122 options = command.params;
123 for (i = 1; i < options.length; i++) {
124 option = options[i].split("=", 2);
125 option[0] = option[0].toUpperCase();
126 this.irc_connection.options[option[0]] = (typeof option[1] !== 'undefined') ? option[1] : true;
127 if (_.include(['NETWORK', 'PREFIX', 'CHANTYPES', 'CHANMODES', 'NAMESX'], option[0])) {
128 if (option[0] === 'PREFIX') {
129 matches = /\(([^)]*)\)(.*)/.exec(option[1]);
130 if ((matches) && (matches.length === 3)) {
131 this.irc_connection.options.PREFIX = [];
132 for (j = 0; j < matches[2].length; j++) {
133 this.irc_connection.options.PREFIX.push({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)});
134 }
135 }
136 } else if (option[0] === 'CHANTYPES') {
137 this.irc_connection.options.CHANTYPES = this.irc_connection.options.CHANTYPES.split('');
138 } else if (option[0] === 'CHANMODES') {
139 this.irc_connection.options.CHANMODES = option[1].split(',');
140 } else if ((option[0] === 'NAMESX') && (!_.contains(this.irc_connection.cap.enabled, 'multi-prefix'))) {
141 this.irc_connection.write('PROTOCTL NAMESX');
142 }
143 }
144 }
145 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' options', {
146 options: this.irc_connection.options,
147 cap: this.irc_connection.cap.enabled
148 });
149 },
150
151 'RPL_ENDOFWHOIS': function (command) {
152 this.irc_connection.emit('user ' + command.params[1] + ' endofwhois', {
153 nick: command.params[1],
154 msg: command.trailing
155 });
156 },
157
158 'RPL_AWAY': function (command) {
159 this.irc_connection.emit('user ' + command.params[1] + ' whoisaway', {
160 nick: command.params[1],
161 reason: command.trailing
162 });
163 },
164
165 'RPL_WHOISUSER': function (command) {
166 this.irc_connection.emit('user ' + command.params[1] + ' whoisuser', {
167 nick: command.params[1],
168 ident: command.params[2],
169 host: command.params[3],
170 msg: command.trailing
171 });
172 },
173
174 'RPL_WHOISSERVER': function (command) {
175 this.irc_connection.emit('user ' + command.params[1] + ' whoisserver', {
176 nick: command.params[1],
177 irc_server: command.params[2],
178 server_info: command.trailing
179 });
180 },
181
182 'RPL_WHOISOPERATOR': function (command) {
183 this.irc_connection.emit('user ' + command.params[1] + ' whoisoperator', {
184 nick: command.params[1],
185 msg: command.trailing
186 });
187 },
188
189 'RPL_WHOISCHANNELS': function (command) {
190 this.irc_connection.emit('user ' + command.params[1] + ' whoischannels', {
191 nick: command.params[1],
192 chans: command.trailing
193 });
194 },
195
196 'RPL_WHOISMODES': function (command) {
197 this.irc_connection.emit('user ' + command.params[1] + ' whoismodes', {
198 nick: command.params[1],
199 msg: command.trailing
200 });
201 },
202
203 'RPL_WHOISIDLE': function (command) {
204 this.irc_connection.emit('user ' + command.params[1] + ' whoisidle', {
205 nick: command.params[1],
206 idle: command.params[2],
207 logon: command.params[3] || undefined
208 });
209 },
210
211 'RPL_WHOISREGNICK': function (command) {
212 this.irc_connection.emit('user ' + command.params[1] + ' whoisregnick', {
213 nick: command.params[1],
214 msg: command.trailing
215 });
216 },
217
218 'RPL_WHOWASUSER': function (command) {
219 this.irc_connection.emit('user ' + command.params[1] + ' whowas', {
220 nick: command.params[1],
221 ident: command.params[2],
222 host: command.params[3],
223 real_name: command.trailing
224 });
225 },
226
227 'RPL_ENDOFWHOWAS': function (command) {
228 this.irc_connection.emit('user ' + command.params[1] + ' endofwhowas', {
229 nick: command.params[1]
230 });
231 },
232
233 'ERR_WASNOSUCHNICK': function (command) {
234 this.irc_connection.emit('user ' + command.params[1] + ' wasnosucknick', {
235 nick: command.params[1]
236 });
237 },
238
239 'RPL_LISTSTART': function (command) {
240 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_start', {});
241 },
242
243 'RPL_LISTEND': function (command) {
244 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_end', {});
245 },
246
247 'RPL_LIST': function (command) {
248 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_channel', {
249 channel: command.params[1],
250 num_users: parseInt(command.params[2], 10),
251 topic: command.trailing
252 });
253 },
254
255 'RPL_MOTD': function (command) {
256 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd', {
257 motd: command.trailing + '\n'
258 });
259 },
260
261 'RPL_MOTDSTART': function (command) {
262 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd_start', {});
263 },
264
265 'RPL_ENDOFMOTD': function (command) {
266 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd_end', {});
267 },
268
269 'RPL_NAMEREPLY': function (command) {
270 var members = command.trailing.split(' ');
271 var member_list = [];
272 var that = this;
273 _.each(members, function (member) {
274 var i = 0,
275 j = 0,
276 modes = [];
277
278 // Make sure we have some prefixes already
279 if (that.irc_connection.options.PREFIX) {
280 for (j = 0; j < that.irc_connection.options.PREFIX.length; j++) {
281 if (member.charAt(i) === that.irc_connection.options.PREFIX[j].symbol) {
282 modes.push(that.irc_connection.options.PREFIX[j].mode);
283 i++;
284 }
285 }
286 }
287
288 member_list.push({nick: member, modes: modes});
289 });
290
291 this.irc_connection.emit('channel ' + command.params[2] + ' userlist', {
292 users: member_list,
293 channel: command.params[2]
294 });
295 },
296
297 'RPL_ENDOFNAMES': function (command) {
298 this.irc_connection.emit('channel ' + command.params[1] + ' userlist_end', {
299 channel: command.params[1]
300 });
301 },
302
303 'RPL_BANLIST': function (command) {
304 this.irc_connection.emit('channel ' + command.params[1] + ' banlist', {
305 channel: command.params[1],
306 banned: command.params[2],
307 banned_by: command.params[3],
308 banned_at: command.params[4]
309 });
310 },
311
312 'RPL_ENDOFBANLIST': function (command) {
313 this.irc_connection.emit('channel ' + command.params[1] + ' banlist_end', {
314 channel: command.params[1]
315 });
316 },
317
318 'RPL_TOPIC': function (command) {
319 this.irc_connection.emit('channel ' + command.params[1] + ' topic', {
320 channel: command.params[1],
321 topic: command.trailing
322 });
323 },
324
325 'RPL_NOTOPIC': function (command) {
326 this.irc_connection.emit('channel ' + command.params[1] + ' topic', {
327 channel: command.params[1],
328 topic: ''
329 });
330 },
331
332 'RPL_TOPICWHOTIME': function (command) {
333 this.irc_connection.emit('channel ' + command.params[1] + ' topicsetby', {
334 nick: command.params[2],
335 channel: command.params[1],
336 when: command.params[3]
337 });
338 },
339
340 'PING': function (command) {
341 this.irc_connection.write('PONG ' + command.trailing);
342 },
343
344 'JOIN': function (command) {
345 var channel;
346 if (typeof command.trailing === 'string' && command.trailing !== '') {
347 channel = command.trailing;
348 } else if (typeof command.params[0] === 'string' && command.params[0] !== '') {
349 channel = command.params[0];
350 }
351
352 this.irc_connection.emit('channel ' + channel + ' join', {
353 nick: command.nick,
354 ident: command.ident,
355 hostname: command.hostname,
356 channel: channel
357 });
358 },
359
360 'PART': function (command) {
361 this.irc_connection.emit('channel ' + command.params[0] + ' part', {
362 nick: command.nick,
363 ident: command.ident,
364 hostname: command.hostname,
365 channel: command.params[0],
366 message: command.trailing
367 });
368 },
369
370 'KICK': function (command) {
371 this.irc_connection.emit('channel ' + command.params[0] + ' kick', {
372 kicked: command.params[1],
373 nick: command.nick,
374 ident: command.ident,
375 hostname: command.hostname,
376 channel: command.params[0],
377 message: command.trailing
378 });
379 },
380
381 'QUIT': function (command) {
382 this.irc_connection.emit('user ' + command.nick + ' quit', {
383 nick: command.nick,
384 ident: command.ident,
385 hostname: command.hostname,
386 message: command.trailing
387 });
388 },
389
390 'NOTICE': function (command) {
391 var namespace;
392
393 if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
394 // It's a CTCP response
395 namespace = (command.params[0] == this.irc_connection.nick) ? 'user' : 'channel';
396 this.irc_connection.emit(namespace + ' ' + command.params[0] + ' ctcp_response', {
397 nick: command.nick,
398 ident: command.ident,
399 hostname: command.hostname,
400 channel: command.params[0],
401 msg: command.trailing.substr(1, command.trailing.length - 2)
402 });
403 } else {
404 namespace = (command.params[0] == this.irc_connection.nick || command.params[0] == '*') ?
405 'user' :
406 'channel';
407
408 this.irc_connection.emit(namespace + ' ' + command.params[0] + ' notice', {
409 from_server: command.prefix ? true : false,
410 nick: command.nick || command.prefix || undefined,
411 ident: command.ident,
412 hostname: command.hostname,
413 target: command.params[0],
414 msg: command.trailing
415 });
416 }
417 },
418
419 'NICK': function (command) {
420 this.irc_connection.emit('user ' + command.nick + ' nick', {
421 nick: command.nick,
422 ident: command.ident,
423 hostname: command.hostname,
424 newnick: command.trailing || command.params[0]
425 });
426 },
427
428 'TOPIC': function (command) {
429 // If we don't have an associated channel, no need to continue
430 if (!command.params[0]) return;
431
432 var channel = command.params[0],
433 topic = command.trailing || '';
434
435 this.irc_connection.emit('channel ' + channel + ' topic', {
436 nick: command.nick,
437 channel: channel,
438 topic: topic
439 });
440 },
441
442 'MODE': function (command) {
443 var chanmodes = this.irc_connection.options.CHANMODES || [],
444 prefixes = this.irc_connection.options.PREFIX || [],
445 always_param = (chanmodes[0] || '').concat((chanmodes[1] || '')),
446 modes = [],
447 has_param, i, j, add, event;
448
449 prefixes = _.reduce(prefixes, function (list, prefix) {
450 list.push(prefix.mode);
451 return list;
452 }, []);
453 always_param = always_param.split('').concat(prefixes);
454
455 has_param = function (mode, add) {
456 if (_.find(always_param, function (m) {
457 return m === mode;
458 })) {
459 return true;
460 } else if (add && _.find((chanmodes[2] || '').split(''), function (m) {
461 return m === mode;
462 })) {
463 return true;
464 } else {
465 return false;
466 }
467 };
468
469 if (!command.params[1]) {
470 command.params[1] = command.trailing;
471 }
472
473 j = 0;
474 for (i = 0; i < command.params[1].length; i++) {
475 switch (command.params[1][i]) {
476 case '+':
477 add = true;
478 break;
479 case '-':
480 add = false;
481 break;
482 default:
483 if (has_param(command.params[1][i], add)) {
484 modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: command.params[2 + j]});
485 j++;
486 } else {
487 modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: null});
488 }
489 }
490 }
491
492 event = (_.contains(this.irc_connection.options.CHANTYPES, command.params[0][0]) ? 'channel ' : 'user ') + command.params[0] + ' mode';
493
494 this.irc_connection.emit(event, {
495 target: command.params[0],
496 nick: command.nick || command.prefix || '',
497 modes: modes
498 });
499 },
500
501 'PRIVMSG': function (command) {
502 var tmp, namespace;
503 if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
504 //CTCP request
505 if (command.trailing.substr(1, 6) === 'ACTION') {
506 this.client.sendIrcCommand('action', {server: this.con_num, nick: command.nick, ident: command.ident, hostname: command.hostname, channel: command.params[0], msg: command.trailing.substr(7, command.trailing.length - 2)});
507 } else if (command.trailing.substr(1, 4) === 'KIWI') {
508 tmp = command.trailing.substr(6, command.trailing.length - 2);
509 namespace = tmp.split(' ', 1)[0];
510 this.client.sendIrcCommand('kiwi', {server: this.con_num, namespace: namespace, data: tmp.substr(namespace.length + 1)});
511 } else if (command.trailing.substr(1, 7) === 'VERSION') {
512 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'VERSION KiwiIRC' + String.fromCharCode(1));
513 } else if (command.trailing.substr(1, 6) === 'SOURCE') {
514 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'SOURCE http://www.kiwiirc.com/' + String.fromCharCode(1));
515 } else if (command.trailing.substr(1, 10) === 'CLIENTINFO') {
516 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'CLIENTINFO SOURCE VERSION TIME' + String.fromCharCode(1));
517 } else {
518 namespace = (command.params[0].toLowerCase() == this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel';
519 this.irc_connection.emit(namespace + ' ' + command.nick + ' ctcp_request', {
520 nick: command.nick,
521 ident: command.ident,
522 hostname: command.hostname,
523 target: command.params[0],
524 type: (command.trailing.substr(1, command.trailing.length - 2).split(' ') || [null])[0],
525 msg: command.trailing.substr(1, command.trailing.length - 2)
526 });
527 }
528 } else {
529 // A message to a user (private message) or to a channel?
530 namespace = (command.params[0] === this.irc_connection.nick) ? 'user ' + command.nick : 'channel ' + command.params[0];
531 this.irc_connection.emit(namespace + ' privmsg', {
532 nick: command.nick,
533 ident: command.ident,
534 hostname: command.hostname,
535 channel: command.params[0],
536 msg: command.trailing
537 });
538 }
539 },
540
541 'CAP': function (command) {
542 // TODO: capability modifiers
543 // i.e. - for disable, ~ for requires ACK, = for sticky
544 var capabilities = command.trailing.replace(/[\-~=]/, '').split(' ');
545 var request;
546
547 // Which capabilities we want to enable
548 var want = ['multi-prefix', 'away-notify'];
549
550 if (this.irc_connection.password) {
551 want.push('sasl');
552 }
553
554 switch (command.params[1]) {
555 case 'LS':
556 // Compute which of the available capabilities we want and request them
557 request = _.intersection(capabilities, want);
558 if (request.length > 0) {
559 this.irc_connection.cap.requested = request;
560 this.irc_connection.write('CAP REQ :' + request.join(' '));
561 } else {
562 this.irc_connection.write('CAP END');
563 this.irc_connection.cap_negotation = false;
564 }
565 break;
566 case 'ACK':
567 if (capabilities.length > 0) {
568 // Update list of enabled capabilities
569 this.irc_connection.cap.enabled = capabilities;
570 // Update list of capabilities we would like to have but that aren't enabled
571 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
572 }
573 if (this.irc_connection.cap.enabled.length > 0) {
574 if (_.contains(this.irc_connection.cap.enabled, 'sasl')) {
575 this.irc_connection.sasl = true;
576 this.irc_connection.write('AUTHENTICATE PLAIN');
577 } else {
578 this.irc_connection.write('CAP END');
579 this.irc_connection.cap_negotation = false;
580 }
581 }
582 break;
583 case 'NAK':
584 if (capabilities.length > 0) {
585 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
586 }
587 if (this.irc_connection.cap.requested.length > 0) {
588 this.irc_connection.write('CAP END');
589 this.irc_connection.cap_negotation = false;
590 }
591 break;
592 case 'LIST':
593 // should we do anything here?
594 break;
595 }
596 },
597
598 'AUTHENTICATE': function (command) {
599 var b = new Buffer(this.irc_connection.nick + "\0" + this.irc_connection.nick + "\0" + this.irc_connection.password, 'utf8');
600 var b64 = b.toString('base64');
601 if (command.params[0] === '+') {
602 while (b64.length >= 400) {
603 this.irc_connection.write('AUTHENTICATE ' + b64.slice(0, 399));
604 b64 = b64.slice(399);
605 }
606 if (b64.length > 0) {
607 this.irc_connection.write('AUTHENTICATE ' + b64);
608 } else {
609 this.irc_connection.write('AUTHENTICATE +');
610 }
611 } else {
612 this.irc_connection.write('CAP END');
613 this.irc_connection.cap_negotation = false;
614 }
615 },
616
617 'AWAY': function (command) {
618 this.irc_connection.emit('user ' + command.nick + ' away', {
619 nick: command.nick,
620 msg: command.trailing
621 });
622 },
623
624 'RPL_SASLAUTHENTICATED': function (command) {
625 this.irc_connection.write('CAP END');
626 this.irc_connection.cap_negotation = false;
627 this.irc_connection.sasl = true;
628 },
629
630 'RPL_SASLLOGGEDIN': function (command) {
631 if (this.irc_connection.cap_negotation === false) {
632 this.irc_connection.write('CAP END');
633 }
634 },
635
636 'ERR_SASLNOTAUTHORISED': function (command) {
637 this.irc_connection.write('CAP END');
638 this.irc_connection.cap_negotation = false;
639 },
640
641 'ERR_SASLABORTED': function (command) {
642 this.irc_connection.write('CAP END');
643 this.irc_connection.cap_negotation = false;
644 },
645
646 'ERR_SASLALREADYAUTHED': function (command) {
647 // noop
648 },
649
650 'ERROR': function (command) {
651 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' error', {
652 reason: command.trailing
653 });
654 },
655 ERR_PASSWDMISMATCH: function (command) {
656 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' password_mismatch', {});
657 },
658
659 ERR_LINKCHANNEL: function (command) {
660 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_redirect', {
661 from: command.params[1],
662 to: command.params[2]
663 });
664 },
665
666 ERR_NOSUCHNICK: function (command) {
667 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' no_such_nick', {
668 nick: command.params[1],
669 reason: command.trailing
670 });
671 },
672
673 ERR_CANNOTSENDTOCHAN: function (command) {
674 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' cannot_send_to_chan', {
675 channel: command.params[1],
676 reason: command.trailing
677 });
678 },
679
680 ERR_TOOMANYCHANNELS: function (command) {
681 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' too_many_channels', {
682 channel: command.params[1],
683 reason: command.trailing
684 });
685 },
686
687 ERR_USERNOTINCHANNEL: function (command) {
688 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' user_not_in_channel', {
689 nick: command.params[0],
690 channel: command.params[1],
691 reason: command.trailing
692 });
693 },
694
695 ERR_NOTONCHANNEL: function (command) {
696 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' not_on_channel', {
697 channel: command.params[1],
698 reason: command.trailing
699 });
700 },
701
702 ERR_CHANNELISFULL: function (command) {
703 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_is_full', {
704 channel: command.params[1],
705 reason: command.trailing
706 });
707 },
708
709 ERR_INVITEONLYCHAN: function (command) {
710 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' invite_only_channel', {
711 channel: command.params[1],
712 reason: command.trailing
713 });
714 },
715
716 ERR_BANNEDFROMCHAN: function (command) {
717 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' banned_from_channel', {
718 channel: command.params[1],
719 reason: command.trailing
720 });
721 },
722
723 ERR_BADCHANNELKEY: function (command) {
724 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' bad_channel_key', {
725 channel: command.params[1],
726 reason: command.trailing
727 });
728 },
729
730 ERR_CHANOPRIVSNEEDED: function (command) {
731 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' chanop_privs_needed', {
732 channel: command.params[1],
733 reason: command.trailing
734 });
735 },
736
737 ERR_NICKNAMEINUSE: function (command) {
738 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' nickname_in_use', {
739 nick: command.params[1],
740 reason: command.trailing
741 });
742 },
743
744 ERR_ERRONEUSNICKNAME: function(command) {
745 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' erroneus_nickname', {
746 nick: command.params[1],
747 reason: command.trailing
748 });
749 },
750
751 ERR_NOTREGISTERED: function (command) {
752 },
753
754 RPL_MAPMORE: function (command) {
755 var params = _.clone(command.params);
756 params.shift();
757 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
758 },
759
760 RPL_MAPEND: function (command) {
761 var params = _.clone(command.params);
762 params.shift();
763 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
764 },
765
766 RPL_LINKS: function (command) {
767 var params = _.clone(command.params);
768 params.shift();
769 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
770 },
771
772 RPL_ENDOFLINKS: function (command) {
773 var params = _.clone(command.params);
774 params.shift();
775 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
776 },
777
778 ERR_UNKNOWNCOMMAND: function (command) {
779 var params = _.clone(command.params);
780 params.shift();
781 genericNotice.call(this, command, '`' + params.join(', ') + '` ' + command.trailing);
782 },
783
784 ERR_NOMOTD: function (command) {
785 var params = _.clone(command.params);
786 params.shift();
787 genericNotice.call(this, command, command.trailing);
788 },
789
790 ERR_NOPRIVILEGES: function (command) {
791 var params = _.clone(command.params);
792 params.shift();
793 genericNotice.call(this, command, command.trailing);
794 },
795
796 RPL_STATSCONN: function (command) {
797 var params = _.clone(command.params);
798 params.shift();
799 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
800 },
801
802 RPL_LUSERCLIENT: function (command) {
803 var params = _.clone(command.params);
804 params.shift();
805 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
806 },
807
808 RPL_LUSEROP: function (command) {
809 var params = _.clone(command.params);
810 params.shift();
811 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
812 },
813
814 RPL_LUSERUNKNOWN: function (command) {
815 var params = _.clone(command.params);
816 params.shift();
817 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
818 },
819
820 RPL_LUSERCHANNELS: function (command) {
821 var params = _.clone(command.params);
822 params.shift();
823 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
824 },
825
826 RPL_LUSERME: function (command) {
827 var params = _.clone(command.params);
828 params.shift();
829 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
830 },
831
832 RPL_LOCALUSERS: function (command) {
833 var params = _.clone(command.params);
834 params.shift();
835 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
836 },
837
838 RPL_GLOBALUSERS: function (command) {
839 var params = _.clone(command.params);
840 params.shift();
841 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
842 }
843 };
844
845
846
847
848 function genericNotice (command, msg, is_error) {
849 // Default to being an error
850 if (typeof is_error !== 'boolean')
851 is_error = true;
852
853 this.client.sendIrcCommand('notice', {
854 server: this.con_num,
855 from_server: true,
856 nick: command.prefix,
857 ident: '',
858 hostname: '',
859 target: command.params[0],
860 msg: msg,
861 numeric: parseInt(command.command, 10)
862 });
863 }