Handle replies to WHOWAS command
[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 var i = 0;
274 _.each(members, function (member) {
275 var j, k, modes = [];
276
277 // Make sure we have some prefixes already
278 if (that.irc_connection.options.PREFIX) {
279 for (j = 0; j < member.length; j++) {
280 for (k = 0; k < that.irc_connection.options.PREFIX.length; k++) {
281 if (member.charAt(j) === that.irc_connection.options.PREFIX[k].symbol) {
282 modes.push(that.irc_connection.options.PREFIX[k].mode);
283 i++;
284 }
285 }
286 }
287 }
288
289 member_list.push({nick: member, modes: modes});
290 });
291
292 this.irc_connection.emit('channel ' + command.params[2] + ' userlist', {
293 users: member_list,
294 channel: command.params[2]
295 });
296 },
297
298 'RPL_ENDOFNAMES': function (command) {
299 this.irc_connection.emit('channel ' + command.params[1] + ' userlist_end', {
300 channel: command.params[1]
301 });
302 },
303
304 'RPL_BANLIST': function (command) {
305 this.irc_connection.emit('channel ' + command.params[1] + ' banlist', {
306 channel: command.params[1],
307 banned: command.params[2],
308 banned_by: command.params[3],
309 banned_at: command.params[4]
310 });
311 },
312
313 'RPL_ENDOFBANLIST': function (command) {
314 this.irc_connection.emit('channel ' + command.params[1] + ' banlist_end', {
315 channel: command.params[1]
316 });
317 },
318
319 'RPL_TOPIC': function (command) {
320 this.irc_connection.emit('channel ' + command.params[1] + ' topic', {
321 channel: command.params[1],
322 topic: command.trailing
323 });
324 },
325
326 'RPL_NOTOPIC': function (command) {
327 this.irc_connection.emit('channel ' + command.params[1] + ' topic', {
328 channel: command.params[1],
329 topic: ''
330 });
331 },
332
333 'RPL_TOPICWHOTIME': function (command) {
334 this.irc_connection.emit('channel ' + command.params[1] + ' topicsetby', {
335 nick: command.params[2],
336 channel: command.params[1],
337 when: command.params[3]
338 });
339 },
340
341 'PING': function (command) {
342 this.irc_connection.write('PONG ' + command.trailing);
343 },
344
345 'JOIN': function (command) {
346 var channel;
347 if (typeof command.trailing === 'string' && command.trailing !== '') {
348 channel = command.trailing;
349 } else if (typeof command.params[0] === 'string' && command.params[0] !== '') {
350 channel = command.params[0];
351 }
352
353 this.irc_connection.emit('channel ' + channel + ' join', {
354 nick: command.nick,
355 ident: command.ident,
356 hostname: command.hostname,
357 channel: channel
358 });
359 },
360
361 'PART': function (command) {
362 this.irc_connection.emit('channel ' + command.params[0] + ' part', {
363 nick: command.nick,
364 ident: command.ident,
365 hostname: command.hostname,
366 channel: command.params[0],
367 message: command.trailing
368 });
369 },
370
371 'KICK': function (command) {
372 this.irc_connection.emit('channel ' + command.params[0] + ' kick', {
373 kicked: command.params[1],
374 nick: command.nick,
375 ident: command.ident,
376 hostname: command.hostname,
377 channel: command.params[0],
378 message: command.trailing
379 });
380 },
381
382 'QUIT': function (command) {
383 this.irc_connection.emit('user ' + command.nick + ' quit', {
384 nick: command.nick,
385 ident: command.ident,
386 hostname: command.hostname,
387 message: command.trailing
388 });
389 },
390
391 'NOTICE': function (command) {
392 var namespace;
393
394 if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
395 // It's a CTCP response
396 namespace = (command.params[0] == this.irc_connection.nick) ? 'user' : 'channel';
397 this.irc_connection.emit(namespace + ' ' + command.params[0] + ' ctcp_response', {
398 nick: command.nick,
399 ident: command.ident,
400 hostname: command.hostname,
401 channel: command.params[0],
402 msg: command.trailing.substr(1, command.trailing.length - 2)
403 });
404 } else {
405 namespace = (command.params[0] == this.irc_connection.nick || command.params[0] == '*') ?
406 'user' :
407 'channel';
408
409 this.irc_connection.emit(namespace + ' ' + command.params[0] + ' notice', {
410 from_server: command.prefix ? true : false,
411 nick: command.nick || command.prefix || undefined,
412 ident: command.ident,
413 hostname: command.hostname,
414 target: command.params[0],
415 msg: command.trailing
416 });
417 }
418 },
419
420 'NICK': function (command) {
421 this.irc_connection.emit('user ' + command.nick + ' nick', {
422 nick: command.nick,
423 ident: command.ident,
424 hostname: command.hostname,
425 newnick: command.trailing || command.params[0]
426 });
427 },
428
429 'TOPIC': function (command) {
430 // If we don't have an associated channel, no need to continue
431 if (!command.params[0]) return;
432
433 var channel = command.params[0],
434 topic = command.trailing || '';
435
436 this.irc_connection.emit('channel ' + channel + ' topic', {
437 nick: command.nick,
438 channel: channel,
439 topic: topic
440 });
441 },
442
443 'MODE': function (command) {
444 var chanmodes = this.irc_connection.options.CHANMODES || [],
445 prefixes = this.irc_connection.options.PREFIX || [],
446 always_param = (chanmodes[0] || '').concat((chanmodes[1] || '')),
447 modes = [],
448 has_param, i, j, add, event;
449
450 prefixes = _.reduce(prefixes, function (list, prefix) {
451 list.push(prefix.mode);
452 return list;
453 }, []);
454 always_param = always_param.split('').concat(prefixes);
455
456 has_param = function (mode, add) {
457 if (_.find(always_param, function (m) {
458 return m === mode;
459 })) {
460 return true;
461 } else if (add && _.find((chanmodes[2] || '').split(''), function (m) {
462 return m === mode;
463 })) {
464 return true;
465 } else {
466 return false;
467 }
468 };
469
470 if (!command.params[1]) {
471 command.params[1] = command.trailing;
472 }
473
474 j = 0;
475 for (i = 0; i < command.params[1].length; i++) {
476 switch (command.params[1][i]) {
477 case '+':
478 add = true;
479 break;
480 case '-':
481 add = false;
482 break;
483 default:
484 if (has_param(command.params[1][i], add)) {
485 modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: command.params[2 + j]});
486 j++;
487 } else {
488 modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: null});
489 }
490 }
491 }
492
493 event = (_.contains(this.irc_connection.options.CHANTYPES, command.params[0][0]) ? 'channel ' : 'user ') + command.params[0] + ' mode';
494
495 this.irc_connection.emit(event, {
496 target: command.params[0],
497 nick: command.nick || command.prefix || '',
498 modes: modes
499 });
500 },
501
502 'PRIVMSG': function (command) {
503 var tmp, namespace;
504 if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
505 //CTCP request
506 if (command.trailing.substr(1, 6) === 'ACTION') {
507 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)});
508 } else if (command.trailing.substr(1, 4) === 'KIWI') {
509 tmp = command.trailing.substr(6, command.trailing.length - 2);
510 namespace = tmp.split(' ', 1)[0];
511 this.client.sendIrcCommand('kiwi', {server: this.con_num, namespace: namespace, data: tmp.substr(namespace.length + 1)});
512 } else if (command.trailing.substr(1, 7) === 'VERSION') {
513 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'VERSION KiwiIRC' + String.fromCharCode(1));
514 } else if (command.trailing.substr(1, 6) === 'SOURCE') {
515 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'SOURCE http://www.kiwiirc.com/' + String.fromCharCode(1));
516 } else if (command.trailing.substr(1, 10) === 'CLIENTINFO') {
517 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'CLIENTINFO SOURCE VERSION TIME' + String.fromCharCode(1));
518 } else {
519 namespace = (command.params[0].toLowerCase() == this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel';
520 this.irc_connection.emit(namespace + ' ' + command.nick + ' ctcp_request', {
521 nick: command.nick,
522 ident: command.ident,
523 hostname: command.hostname,
524 target: command.params[0],
525 type: (command.trailing.substr(1, command.trailing.length - 2).split(' ') || [null])[0],
526 msg: command.trailing.substr(1, command.trailing.length - 2)
527 });
528 }
529 } else {
530 // A message to a user (private message) or to a channel?
531 namespace = (command.params[0] === this.irc_connection.nick) ? 'user ' + command.nick : 'channel ' + command.params[0];
532 this.irc_connection.emit(namespace + ' privmsg', {
533 nick: command.nick,
534 ident: command.ident,
535 hostname: command.hostname,
536 channel: command.params[0],
537 msg: command.trailing
538 });
539 }
540 },
541
542 'CAP': function (command) {
543 // TODO: capability modifiers
544 // i.e. - for disable, ~ for requires ACK, = for sticky
545 var capabilities = command.trailing.replace(/[\-~=]/, '').split(' ');
546 var request;
547
548 // Which capabilities we want to enable
549 var want = ['multi-prefix', 'away-notify'];
550
551 if (this.irc_connection.password) {
552 want.push('sasl');
553 }
554
555 switch (command.params[1]) {
556 case 'LS':
557 // Compute which of the available capabilities we want and request them
558 request = _.intersection(capabilities, want);
559 if (request.length > 0) {
560 this.irc_connection.cap.requested = request;
561 this.irc_connection.write('CAP REQ :' + request.join(' '));
562 } else {
563 this.irc_connection.write('CAP END');
564 this.irc_connection.cap_negotation = false;
565 }
566 break;
567 case 'ACK':
568 if (capabilities.length > 0) {
569 // Update list of enabled capabilities
570 this.irc_connection.cap.enabled = capabilities;
571 // Update list of capabilities we would like to have but that aren't enabled
572 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
573 }
574 if (this.irc_connection.cap.enabled.length > 0) {
575 if (_.contains(this.irc_connection.cap.enabled, 'sasl')) {
576 this.irc_connection.sasl = true;
577 this.irc_connection.write('AUTHENTICATE PLAIN');
578 } else {
579 this.irc_connection.write('CAP END');
580 this.irc_connection.cap_negotation = false;
581 }
582 }
583 break;
584 case 'NAK':
585 if (capabilities.length > 0) {
586 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
587 }
588 if (this.irc_connection.cap.requested.length > 0) {
589 this.irc_connection.write('CAP END');
590 this.irc_connection.cap_negotation = false;
591 }
592 break;
593 case 'LIST':
594 // should we do anything here?
595 break;
596 }
597 },
598
599 'AUTHENTICATE': function (command) {
600 var b = new Buffer(this.irc_connection.nick + "\0" + this.irc_connection.nick + "\0" + this.irc_connection.password, 'utf8');
601 var b64 = b.toString('base64');
602 if (command.params[0] === '+') {
603 while (b64.length >= 400) {
604 this.irc_connection.write('AUTHENTICATE ' + b64.slice(0, 399));
605 b64 = b64.slice(399);
606 }
607 if (b64.length > 0) {
608 this.irc_connection.write('AUTHENTICATE ' + b64);
609 } else {
610 this.irc_connection.write('AUTHENTICATE +');
611 }
612 } else {
613 this.irc_connection.write('CAP END');
614 this.irc_connection.cap_negotation = false;
615 }
616 },
617
618 'AWAY': function (command) {
619 this.irc_connection.emit('user ' + command.nick + ' away', {
620 nick: command.nick,
621 msg: command.trailing
622 });
623 },
624
625 'RPL_SASLAUTHENTICATED': function (command) {
626 this.irc_connection.write('CAP END');
627 this.irc_connection.cap_negotation = false;
628 this.irc_connection.sasl = true;
629 },
630
631 'RPL_SASLLOGGEDIN': function (command) {
632 if (this.irc_connection.cap_negotation === false) {
633 this.irc_connection.write('CAP END');
634 }
635 },
636
637 'ERR_SASLNOTAUTHORISED': function (command) {
638 this.irc_connection.write('CAP END');
639 this.irc_connection.cap_negotation = false;
640 },
641
642 'ERR_SASLABORTED': function (command) {
643 this.irc_connection.write('CAP END');
644 this.irc_connection.cap_negotation = false;
645 },
646
647 'ERR_SASLALREADYAUTHED': function (command) {
648 // noop
649 },
650
651 'ERROR': function (command) {
652 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' error', {
653 reason: command.trailing
654 });
655 },
656 ERR_PASSWDMISMATCH: function (command) {
657 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' password_mismatch', {});
658 },
659
660 ERR_LINKCHANNEL: function (command) {
661 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_redirect', {
662 from: command.params[1],
663 to: command.params[2]
664 });
665 },
666
667 ERR_NOSUCHNICK: function (command) {
668 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' no_such_nick', {
669 nick: command.params[1],
670 reason: command.trailing
671 });
672 },
673
674 ERR_CANNOTSENDTOCHAN: function (command) {
675 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' cannot_send_to_chan', {
676 channel: command.params[1],
677 reason: command.trailing
678 });
679 },
680
681 ERR_TOOMANYCHANNELS: function (command) {
682 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' too_many_channels', {
683 channel: command.params[1],
684 reason: command.trailing
685 });
686 },
687
688 ERR_USERNOTINCHANNEL: function (command) {
689 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' user_not_in_channel', {
690 nick: command.params[0],
691 channel: command.params[1],
692 reason: command.trailing
693 });
694 },
695
696 ERR_NOTONCHANNEL: function (command) {
697 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' not_on_channel', {
698 channel: command.params[1],
699 reason: command.trailing
700 });
701 },
702
703 ERR_CHANNELISFULL: function (command) {
704 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_is_full', {
705 channel: command.params[1],
706 reason: command.trailing
707 });
708 },
709
710 ERR_INVITEONLYCHAN: function (command) {
711 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' invite_only_channel', {
712 channel: command.params[1],
713 reason: command.trailing
714 });
715 },
716
717 ERR_BANNEDFROMCHAN: function (command) {
718 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' banned_from_channel', {
719 channel: command.params[1],
720 reason: command.trailing
721 });
722 },
723
724 ERR_BADCHANNELKEY: function (command) {
725 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' bad_channel_key', {
726 channel: command.params[1],
727 reason: command.trailing
728 });
729 },
730
731 ERR_CHANOPRIVSNEEDED: function (command) {
732 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' chanop_privs_needed', {
733 channel: command.params[1],
734 reason: command.trailing
735 });
736 },
737
738 ERR_NICKNAMEINUSE: function (command) {
739 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' nickname_in_use', {
740 nick: command.params[1],
741 reason: command.trailing
742 });
743 },
744
745 ERR_ERRONEUSNICKNAME: function(command) {
746 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' erroneus_nickname', {
747 nick: command.params[1],
748 reason: command.trailing
749 });
750 },
751
752 ERR_NOTREGISTERED: function (command) {
753 },
754
755 RPL_MAPMORE: function (command) {
756 var params = _.clone(command.params);
757 params.shift();
758 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
759 },
760
761 RPL_MAPEND: function (command) {
762 var params = _.clone(command.params);
763 params.shift();
764 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
765 },
766
767 RPL_LINKS: function (command) {
768 var params = _.clone(command.params);
769 params.shift();
770 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
771 },
772
773 RPL_ENDOFLINKS: function (command) {
774 var params = _.clone(command.params);
775 params.shift();
776 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
777 },
778
779 ERR_UNKNOWNCOMMAND: function (command) {
780 var params = _.clone(command.params);
781 params.shift();
782 genericNotice.call(this, command, '`' + params.join(', ') + '` ' + command.trailing);
783 },
784
785 ERR_NOMOTD: function (command) {
786 var params = _.clone(command.params);
787 params.shift();
788 genericNotice.call(this, command, command.trailing);
789 },
790
791 ERR_NOPRIVILEGES: function (command) {
792 var params = _.clone(command.params);
793 params.shift();
794 genericNotice.call(this, command, command.trailing);
795 },
796
797 RPL_STATSCONN: function (command) {
798 var params = _.clone(command.params);
799 params.shift();
800 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
801 },
802
803 RPL_LUSERCLIENT: function (command) {
804 var params = _.clone(command.params);
805 params.shift();
806 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
807 },
808
809 RPL_LUSEROP: function (command) {
810 var params = _.clone(command.params);
811 params.shift();
812 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
813 },
814
815 RPL_LUSERUNKNOWN: function (command) {
816 var params = _.clone(command.params);
817 params.shift();
818 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
819 },
820
821 RPL_LUSERCHANNELS: function (command) {
822 var params = _.clone(command.params);
823 params.shift();
824 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
825 },
826
827 RPL_LUSERME: function (command) {
828 var params = _.clone(command.params);
829 params.shift();
830 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
831 },
832
833 RPL_LOCALUSERS: function (command) {
834 var params = _.clone(command.params);
835 params.shift();
836 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
837 },
838
839 RPL_GLOBALUSERS: function (command) {
840 var params = _.clone(command.params);
841 params.shift();
842 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
843 }
844 };
845
846
847
848
849 function genericNotice (command, msg, is_error) {
850 // Default to being an error
851 if (typeof is_error !== 'boolean')
852 is_error = true;
853
854 this.client.sendIrcCommand('notice', {
855 server: this.con_num,
856 from_server: true,
857 nick: command.prefix,
858 ident: '',
859 hostname: '',
860 target: command.params[0],
861 msg: msg,
862 numeric: parseInt(command.command, 10)
863 });
864 }